[cfe-commits] r78645 - in /cfe/trunk: include/clang/AST/StmtNodes.def lib/Sema/CMakeLists.txt lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp lib/Sema/TreeTransform.h

Douglas Gregor dgregor at apple.com
Mon Aug 10 22:31:07 PDT 2009


Author: dgregor
Date: Tue Aug 11 00:31:07 2009
New Revision: 78645

URL: http://llvm.org/viewvc/llvm-project?rev=78645&view=rev
Log:
Refactor the template-instantiation logic for expressions into a
generic tree transformation (also used for recanonicalization) and a
small amount of template-instantiation-specific logic.

Removed:
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
Modified:
    cfe/trunk/include/clang/AST/StmtNodes.def
    cfe/trunk/lib/Sema/CMakeLists.txt
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=78645&r1=78644&r2=78645&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Tue Aug 11 00:31:07 2009
@@ -25,6 +25,10 @@
 #  define EXPR(Type, Base) STMT(Type, Base)
 #endif
 
+#ifndef ABSTRACT_EXPR
+#  define ABSTRACT_EXPR(Type, Base) EXPR(Type, Base)
+#endif
+
 // Normal Statements.
 STMT(NullStmt        , Stmt)
 FIRST_STMT(NullStmt)
@@ -64,7 +68,7 @@
 LAST_STMT(CXXTryStmt)
 
 // Expressions.
-EXPR(Expr                  , Stmt)
+ABSTRACT_EXPR(Expr                  , Stmt)
 FIRST_EXPR(Expr)
 EXPR(PredefinedExpr        , Expr)
 EXPR(DeclRefExpr           , Expr)
@@ -151,8 +155,9 @@
 
 LAST_EXPR(BlockDeclRefExpr)
 
-#undef STMT
+#undef ABSTRACT_EXPR
 #undef EXPR
+#undef STMT
 #undef FIRST_STMT
 #undef LAST_STMT
 #undef FIRST_EXPR

Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=78645&r1=78644&r2=78645&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Tue Aug 11 00:31:07 2009
@@ -26,7 +26,6 @@
   SemaTemplateDeduction.cpp
   SemaTemplateInstantiate.cpp
   SemaTemplateInstantiateDecl.cpp
-  SemaTemplateInstantiateExpr.cpp
   SemaTemplateInstantiateStmt.cpp
   SemaType.cpp
   )

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=78645&r1=78644&r2=78645&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Aug 11 00:31:07 2009
@@ -316,24 +316,30 @@
     /// \brief Returns the name of the entity being instantiated, if any.
     DeclarationName getBaseEntity() { return Entity; }
     
-    /// \brief Transforms an expression by instantiating it with the given
-    /// template arguments.
-    Sema::OwningExprResult TransformExpr(Expr *E);
-
     /// \brief Transform the given declaration by instantiating a reference to
     /// this declaration.
     Decl *TransformDecl(Decl *D);
     
+    Sema::OwningStmtResult TransformStmt(Stmt *S) {
+      return SemaRef.InstantiateStmt(S, TemplateArgs);
+    }
+
+    Sema::OwningStmtResult TransformCompoundStmt(CompoundStmt *S, 
+                                                 bool IsStmtExpr) {
+      return SemaRef.InstantiateCompoundStmt(S, TemplateArgs, IsStmtExpr);
+    }
+    
+    Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E);
+    
+    Sema::OwningExprResult 
+    TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E);
+      
     /// \brief Transforms a template type parameter type by performing 
     /// substitution of the corresponding template type argument.
     QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T);
   };
 }
 
-Sema::OwningExprResult TemplateInstantiator::TransformExpr(Expr *E) {
-  return getSema().InstantiateExpr(E, TemplateArgs);
-}
-
 Decl *TemplateInstantiator::TransformDecl(Decl *D) {
   if (TemplateTemplateParmDecl *TTP 
         = dyn_cast_or_null<TemplateTemplateParmDecl>(D)) {
@@ -351,6 +357,93 @@
   return SemaRef.InstantiateCurrentDeclRef(cast_or_null<NamedDecl>(D));
 }
 
+Sema::OwningExprResult 
+TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
+  // FIXME: Clean this up a bit
+  NamedDecl *D = E->getDecl();
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+    assert(NTTP->getDepth() == 0 && "No nested templates yet");
+    
+    // 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 (NTTP->getPosition() >= TemplateArgs.size() ||
+        TemplateArgs[NTTP->getPosition()].isNull())
+      return SemaRef.Owned(E); // FIXME: Clone the expression!
+    
+    const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; 
+    
+    // The template argument itself might be an expression, in which
+    // case we just return that expression.
+    if (Arg.getKind() == TemplateArgument::Expression)
+      // FIXME: Clone the expression!
+      return SemaRef.Owned(Arg.getAsExpr());
+    
+    if (Arg.getKind() == TemplateArgument::Declaration) {
+      ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+      
+      // FIXME: Can VD ever have a dependent type?
+      return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(), 
+                                      false, false);
+    }
+    
+    assert(Arg.getKind() == TemplateArgument::Integral);
+    QualType T = Arg.getIntegralType();
+    if (T->isCharType() || T->isWideCharType())
+      return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
+                                                                  Arg.getAsIntegral()->getZExtValue(),
+                                                                  T->isWideCharType(),
+                                                                  T, 
+                                                                  E->getSourceRange().getBegin()));
+    if (T->isBooleanType())
+      return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
+                                                                    Arg.getAsIntegral()->getBoolValue(),
+                                                                    T, 
+                                                                    E->getSourceRange().getBegin()));
+    
+    assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
+    return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
+                                                              *Arg.getAsIntegral(),
+                                                              T, 
+                                                              E->getSourceRange().getBegin()));
+  }
+  
+  if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
+    // FIXME: instantiate each decl in the overload set
+    return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Ovl,
+                                                           SemaRef.Context.OverloadTy,
+                                                           E->getLocation(),
+                                                           false, false));
+  }
+  
+  NamedDecl *InstD = SemaRef.InstantiateCurrentDeclRef(D);
+  if (!InstD)
+    return SemaRef.ExprError();
+  
+  // FIXME: nested-name-specifier for QualifiedDeclRefExpr
+  return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD, 
+                                          /*FIXME:*/false,
+                                          /*FIXME:*/0, 
+                                          /*FIXME:*/false);  
+}
+
+Sema::OwningExprResult 
+TemplateInstantiator::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) {
+  VarDecl *Var 
+    = cast_or_null<VarDecl>(SemaRef.InstantiateDecl(E->getVarDecl(),
+                                                    SemaRef.CurContext,
+                                                    TemplateArgs));
+  if (!Var)
+    return SemaRef.ExprError();
+  
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(E->getVarDecl(), Var);
+  return SemaRef.Owned(new (SemaRef.Context) CXXConditionDeclExpr(
+                                                                  E->getStartLoc(), 
+                                                                  SourceLocation(),
+                                                                  Var));
+}
+
 QualType 
 TemplateInstantiator::TransformTemplateTypeParmType(
                                               const TemplateTypeParmType *T) {
@@ -711,6 +804,17 @@
                           ClassTemplateSpec->getTemplateArgs());
 }
 
+Sema::OwningExprResult 
+Sema::InstantiateExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
+  if (!E)
+    return Owned(E);
+  
+  TemplateInstantiator Instantiator(*this, TemplateArgs,
+                                    SourceLocation(),
+                                    DeclarationName());
+  return Instantiator.TransformExpr(E);
+}
+
 /// \brief Instantiate a nested-name-specifier.
 NestedNameSpecifier *
 Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,

Removed: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=78644&view=auto

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (removed)
@@ -1,1377 +0,0 @@
-//===--- SemaTemplateInstantiateExpr.cpp - C++ Template Expr 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 expressions.
-//
-//===----------------------------------------------------------------------===/
-#include "Sema.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Designator.h"
-#include "clang/Lex/Preprocessor.h" // for the identifier table
-#include "llvm/Support/Compiler.h"
-using namespace clang;
-
-namespace {
-  class VISIBILITY_HIDDEN TemplateExprInstantiator 
-    : public StmtVisitor<TemplateExprInstantiator, Sema::OwningExprResult> {
-    Sema &SemaRef;
-    const TemplateArgumentList &TemplateArgs;
-
-  public:
-    typedef Sema::OwningExprResult OwningExprResult;
-
-    TemplateExprInstantiator(Sema &SemaRef, 
-                             const TemplateArgumentList &TemplateArgs)
-      : SemaRef(SemaRef), TemplateArgs(TemplateArgs) { }
-
-    // Declare VisitXXXStmt nodes for all of the expression kinds.
-#define EXPR(Type, Base) OwningExprResult Visit##Type(Type *S);
-#define STMT(Type, Base)
-#include "clang/AST/StmtNodes.def"
-
-    // Base case. We can't get here.
-    Sema::OwningExprResult VisitStmt(Stmt *S) { 
-      S->dump();
-      assert(false && "Cannot instantiate this kind of expression");
-      return SemaRef.ExprError(); 
-    }
-  };
-}
-
-// Base case. We can't get here.
-Sema::OwningExprResult TemplateExprInstantiator::VisitExpr(Expr *E) { 
-  E->dump();
-  assert(false && "Cannot instantiate this kind of expression");
-  return SemaRef.ExprError(); 
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitPredefinedExpr(PredefinedExpr *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitIntegerLiteral(IntegerLiteral *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitFloatingLiteral(FloatingLiteral *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitStringLiteral(StringLiteral *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitCharacterLiteral(CharacterLiteral *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitImaginaryLiteral(ImaginaryLiteral *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitGNUNullExpr(GNUNullExpr *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr(
-                                              UnresolvedFunctionNameExpr *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitTemplateIdRefExpr(TemplateIdRefExpr *E) {
-  TemplateName Template 
-    = SemaRef.InstantiateTemplateName(E->getTemplateName(), 
-                                      E->getTemplateNameLoc(),
-                                      TemplateArgs);
-  // FIXME: Can InstantiateTemplateName report an error?
-  
-  llvm::SmallVector<TemplateArgument, 4> InstantiatedArgs;
-  for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
-    TemplateArgument InstArg = SemaRef.Instantiate(E->getTemplateArgs()[I],
-                                                   TemplateArgs);
-    if (InstArg.isNull())
-      return SemaRef.ExprError();
-    
-    InstantiatedArgs.push_back(InstArg);
-  }
-  
-  // FIXME: It's possible that we'll find out now that the template name 
-  // actually refers to a type, in which case this is a functional cast. 
-  // Implement this!
-  
-  return SemaRef.BuildTemplateIdExpr(Template, E->getTemplateNameLoc(),
-                                     E->getLAngleLoc(),
-                                     InstantiatedArgs.data(),
-                                     InstantiatedArgs.size(),
-                                     E->getRAngleLoc());
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
-  NamedDecl *D = E->getDecl();
-  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
-    assert(NTTP->getDepth() == 0 && "No nested templates yet");
-
-    // 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 (NTTP->getPosition() >= TemplateArgs.size() ||
-        TemplateArgs[NTTP->getPosition()].isNull())
-      return SemaRef.Owned(E->Retain());
-    
-    const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; 
-    
-    // The template argument itself might be an expression, in which
-    // case we just return that expression.
-    if (Arg.getKind() == TemplateArgument::Expression)
-      // FIXME: Clone the expression!
-      return SemaRef.Owned(Arg.getAsExpr());
-
-    if (Arg.getKind() == TemplateArgument::Declaration) {
-      ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
-
-      // FIXME: Can VD ever have a dependent type?
-      return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(), 
-                                      false, false);
-    }
-    
-    assert(Arg.getKind() == TemplateArgument::Integral);
-    QualType T = Arg.getIntegralType();
-    if (T->isCharType() || T->isWideCharType())
-      return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
-                                          Arg.getAsIntegral()->getZExtValue(),
-                                          T->isWideCharType(),
-                                          T, 
-                                       E->getSourceRange().getBegin()));
-    if (T->isBooleanType())
-      return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
-                                          Arg.getAsIntegral()->getBoolValue(),
-                                                 T, 
-                                       E->getSourceRange().getBegin()));
-
-    assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
-    return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
-                                                 *Arg.getAsIntegral(),
-                                                 T, 
-                                       E->getSourceRange().getBegin()));
-  }
-
-  if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
-    // FIXME: instantiate each decl in the overload set
-    return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Ovl,
-                                                   SemaRef.Context.OverloadTy,
-                                                           E->getLocation(),
-                                                           false, false));
-  }
-
-  NamedDecl *InstD = SemaRef.InstantiateCurrentDeclRef(D);
-  if (!InstD)
-    return SemaRef.ExprError();
-
-  // FIXME: nested-name-specifier for QualifiedDeclRefExpr
-  return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD, 
-                                          /*FIXME:*/false,
-                                          /*FIXME:*/0, 
-                                          /*FIXME:*/false);
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitParenExpr(ParenExpr *E) {
-  Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
-  if (SubExpr.isInvalid())
-    return SemaRef.ExprError();
-
-  return SemaRef.Owned(new (SemaRef.Context) ParenExpr(
-                                               E->getLParen(), E->getRParen(), 
-                                               (Expr *)SubExpr.release()));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitUnaryOperator(UnaryOperator *E) {
-  Sema::OwningExprResult Arg = Visit(E->getSubExpr());
-  if (Arg.isInvalid())
-    return SemaRef.ExprError();
-
-  return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(),
-                                      E->getOpcode(),
-                                      move(Arg));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
-  Sema::OwningExprResult LHS = Visit(E->getLHS());
-  if (LHS.isInvalid())
-    return SemaRef.ExprError();
-
-  Sema::OwningExprResult RHS = Visit(E->getRHS());
-  if (RHS.isInvalid())
-    return SemaRef.ExprError();
-
-  // Since the overloaded array-subscript operator (operator[]) can
-  // only be a member function, we can make several simplifying
-  // assumptions here:
-  //   1) Normal name lookup (from the current scope) will not ever
-  //   find any declarations of operator[] that won't also be found be
-  //   member operator lookup, so it is safe to pass a NULL Scope
-  //   during the instantiation to avoid the lookup entirely.
-  //
-  //   2) Neither normal name lookup nor argument-dependent lookup at
-  //   template definition time will find any operators that won't be
-  //   found at template instantiation time, so we do not need to
-  //   cache the results of name lookup as we do for the binary
-  //   operators.
-  SourceLocation LLocFake = ((Expr*)LHS.get())->getSourceRange().getBegin();
-  return SemaRef.ActOnArraySubscriptExpr(/*Scope=*/0, move(LHS),
-                                         /*FIXME:*/LLocFake,
-                                         move(RHS),
-                                         E->getRBracketLoc());
-}
-
-Sema::OwningExprResult TemplateExprInstantiator::VisitCallExpr(CallExpr *E) {
-  // Instantiate callee
-  OwningExprResult Callee = Visit(E->getCallee());
-  if (Callee.isInvalid())
-    return SemaRef.ExprError();
-
-  // Instantiate arguments
-  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
-  llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
-  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
-    OwningExprResult Arg = Visit(E->getArg(I));
-    if (Arg.isInvalid())
-      return SemaRef.ExprError();
-
-    FakeCommaLocs.push_back(
-     SemaRef.PP.getLocForEndOfToken(E->getArg(I)->getSourceRange().getEnd()));
-    Args.push_back(Arg.takeAs<Expr>());
-  }
-
-  SourceLocation FakeLParenLoc 
-    = ((Expr *)Callee.get())->getSourceRange().getBegin();
-  return SemaRef.ActOnCallExpr(/*Scope=*/0, move(Callee), 
-                               /*FIXME:*/FakeLParenLoc,
-                               move_arg(Args),
-                               /*FIXME:*/&FakeCommaLocs.front(), 
-                               E->getRParenLoc());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitMemberExpr(MemberExpr *E) {
-  // Instantiate the base of the expression.
-  OwningExprResult Base = Visit(E->getBase());
-  if (Base.isInvalid())
-    return SemaRef.ExprError();
-
-  // FIXME: Handle declaration names here
-  SourceLocation FakeOperatorLoc = 
-    SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
-  return SemaRef.ActOnMemberReferenceExpr(/*Scope=*/0,
-                                          move(Base), 
-                                          /*FIXME*/FakeOperatorLoc,
-                                          E->isArrow()? tok::arrow 
-                                                      : tok::period,
-                                          E->getMemberLoc(),
-                               /*FIXME:*/*E->getMemberDecl()->getIdentifier(),
-                                   /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
-  SourceLocation FakeTypeLoc 
-    = SemaRef.PP.getLocForEndOfToken(E->getLParenLoc());
-  QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs,
-                                       FakeTypeLoc,
-                                       DeclarationName());
-  if (T.isNull())
-    return SemaRef.ExprError();
-
-  OwningExprResult Init = Visit(E->getInitializer());
-  if (Init.isInvalid())
-    return SemaRef.ExprError();
-
-  return SemaRef.ActOnCompoundLiteral(E->getLParenLoc(),
-                                      T.getAsOpaquePtr(),
-                                      /*FIXME*/E->getLParenLoc(),
-                                      move(Init));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) {
-  Sema::OwningExprResult LHS = Visit(E->getLHS());
-  if (LHS.isInvalid())
-    return SemaRef.ExprError();
-
-  Sema::OwningExprResult RHS = Visit(E->getRHS());
-  if (RHS.isInvalid())
-    return SemaRef.ExprError();
-
-  Sema::OwningExprResult Result
-    = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), 
-                                 E->getOpcode(),
-                                 (Expr *)LHS.get(),
-                                 (Expr *)RHS.get());
-  if (Result.isInvalid())
-    return SemaRef.ExprError();
-
-  LHS.release();
-  RHS.release();
-  return move(Result);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCompoundAssignOperator(
-                                                 CompoundAssignOperator *E) {
-  return VisitBinaryOperator(E);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
-  Sema::OwningExprResult First = Visit(E->getArg(0));
-  if (First.isInvalid())
-    return SemaRef.ExprError();
-
-  Expr *Args[2] = { (Expr *)First.get(), 0 };
-
-  Sema::OwningExprResult Second(SemaRef);
-  if (E->getNumArgs() == 2) {
-    Second = Visit(E->getArg(1));
-
-    if (Second.isInvalid())
-      return SemaRef.ExprError();
-
-    Args[1] = (Expr *)Second.get();
-  }
-
-  if (!E->isTypeDependent()) { 
-    // Since our original expression was not type-dependent, we do not
-    // perform lookup again at instantiation time (C++ [temp.dep]p1).
-    // Instead, we just build the new overloaded operator call
-    // expression.
-    OwningExprResult Callee = Visit(E->getCallee());
-    if (Callee.isInvalid())
-      return SemaRef.ExprError();
-
-    First.release();
-    Second.release();
-
-    return SemaRef.Owned(new (SemaRef.Context) CXXOperatorCallExpr(
-                                                       SemaRef.Context, 
-                                                       E->getOperator(),
-                                                       Callee.takeAs<Expr>(), 
-                                                       Args, E->getNumArgs(),
-                                                       E->getType(), 
-                                                       E->getOperatorLoc()));
-  }
-
-  bool isPostIncDec = E->getNumArgs() == 2 && 
-    (E->getOperator() == OO_PlusPlus || E->getOperator() == OO_MinusMinus);
-  if (E->getNumArgs() == 1 || isPostIncDec) {
-    if (!Args[0]->getType()->isOverloadableType()) {
-      // The argument is not of overloadable type, so try to create a
-      // built-in unary operation.
-      UnaryOperator::Opcode Opc 
-        = UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec);
-
-      return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(), Opc,
-                                          move(First));
-    }
-
-    // Fall through to perform overload resolution
-  } else {
-    assert(E->getNumArgs() == 2 && "Expected binary operation");
-
-    Sema::OwningExprResult Result(SemaRef);
-    if (!Args[0]->getType()->isOverloadableType() && 
-        !Args[1]->getType()->isOverloadableType()) {
-      // Neither of the arguments is an overloadable type, so try to
-      // create a built-in binary operation.
-      BinaryOperator::Opcode Opc = 
-        BinaryOperator::getOverloadedOpcode(E->getOperator());
-      Result = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), Opc, 
-                                          Args[0], Args[1]);
-      if (Result.isInvalid())
-        return SemaRef.ExprError();
-
-      First.release();
-      Second.release();
-      return move(Result);
-    }
-
-    // Fall through to perform overload resolution.
-  }
-
-  // Compute the set of functions that were found at template
-  // definition time.
-  Sema::FunctionSet Functions;
-  DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee());
-  OverloadedFunctionDecl *Overloads 
-    = cast<OverloadedFunctionDecl>(DRE->getDecl());
-  
-  // FIXME: Do we have to check
-  // IsAcceptableNonMemberOperatorCandidate for each of these?
-  for (OverloadedFunctionDecl::function_iterator 
-         F = Overloads->function_begin(),
-         FEnd = Overloads->function_end();
-       F != FEnd; ++F)
-    Functions.insert(*F);
-  
-  // Add any functions found via argument-dependent lookup.
-  DeclarationName OpName 
-    = SemaRef.Context.DeclarationNames.getCXXOperatorName(E->getOperator());
-  SemaRef.ArgumentDependentLookup(OpName, Args, E->getNumArgs(), Functions);
-
-  // Create the overloaded operator invocation.
-  if (E->getNumArgs() == 1 || isPostIncDec) {
-    UnaryOperator::Opcode Opc 
-      = UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec);
-    return SemaRef.CreateOverloadedUnaryOp(E->getOperatorLoc(), Opc,
-                                           Functions, move(First));
-  }
-
-  // FIXME: This would be far less ugly if CreateOverloadedBinOp took in ExprArg
-  // arguments!
-  BinaryOperator::Opcode Opc = 
-    BinaryOperator::getOverloadedOpcode(E->getOperator());
-  OwningExprResult Result 
-    = SemaRef.CreateOverloadedBinOp(E->getOperatorLoc(), Opc, 
-                                    Functions, Args[0], Args[1]);
-
-  if (Result.isInvalid())
-    return SemaRef.ExprError();
-
-  First.release();
-  Second.release();
-  return move(Result);  
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E) {
-  VarDecl *Var 
-    = cast_or_null<VarDecl>(SemaRef.InstantiateDecl(E->getVarDecl(),
-                                                    SemaRef.CurContext,
-                                                    TemplateArgs));
-  if (!Var)
-    return SemaRef.ExprError();
-
-  SemaRef.CurrentInstantiationScope->InstantiatedLocal(E->getVarDecl(), Var);
-  return SemaRef.Owned(new (SemaRef.Context) CXXConditionDeclExpr(
-                                                    E->getStartLoc(), 
-                                                    SourceLocation(),
-                                                    Var));
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitConditionalOperator(ConditionalOperator *E) {
-  Sema::OwningExprResult Cond = Visit(E->getCond());
-  if (Cond.isInvalid())
-    return SemaRef.ExprError();
-
-  Sema::OwningExprResult LHS = SemaRef.InstantiateExpr(E->getLHS(), 
-                                                       TemplateArgs);
-  if (LHS.isInvalid())
-    return SemaRef.ExprError();
-
-  Sema::OwningExprResult RHS = Visit(E->getRHS());
-  if (RHS.isInvalid())
-    return SemaRef.ExprError();
-
-  if (!E->isTypeDependent()) { 
-    // Since our original expression was not type-dependent, we do not
-    // perform lookup again at instantiation time (C++ [temp.dep]p1).
-    // Instead, we just build the new conditional operator call expression.
-    return SemaRef.Owned(new (SemaRef.Context) ConditionalOperator(
-                                                           Cond.takeAs<Expr>(),
-                                                           LHS.takeAs<Expr>(), 
-                                                           RHS.takeAs<Expr>(),
-                                                           E->getType()));
-  }
-
-
-  return SemaRef.ActOnConditionalOp(/*FIXME*/E->getCond()->getLocEnd(),
-                                    /*FIXME*/E->getFalseExpr()->getLocStart(),
-                                    move(Cond), move(LHS), move(RHS));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitAddrLabelExpr(AddrLabelExpr *E) {
-  return SemaRef.ActOnAddrLabel(E->getAmpAmpLoc(),
-                                E->getLabelLoc(),
-                                E->getLabel()->getID());
-}
-
-Sema::OwningExprResult TemplateExprInstantiator::VisitStmtExpr(StmtExpr *E) {
-  Sema::OwningStmtResult SubStmt 
-    = SemaRef.InstantiateCompoundStmt(E->getSubStmt(), TemplateArgs, true);
-  if (SubStmt.isInvalid())
-    return SemaRef.ExprError();
-  
-  return SemaRef.ActOnStmtExpr(E->getLParenLoc(), move(SubStmt),
-                               E->getRParenLoc());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
-  assert(false && "__builtin_types_compatible_p is not legal in C++");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
-  ASTOwningVector<&ActionBase::DeleteExpr> SubExprs(SemaRef);
-  for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) {
-    OwningExprResult SubExpr = Visit(E->getExpr(I));
-    if (SubExpr.isInvalid())
-      return SemaRef.ExprError();
-
-    SubExprs.push_back(SubExpr.takeAs<Expr>());
-  }
-
-  // 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);
-  Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(),
-                                                   E->getBuiltinLoc(), 
-                                                   false, false);
-  SemaRef.UsualUnaryConversions(Callee);
-
-  // Build the CallExpr 
-  CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee,
-                                                     SubExprs.takeAs<Expr>(),
-                                                     SubExprs.size(),
-                                                     Builtin->getResultType(),
-                                                     E->getRParenLoc());
-  OwningExprResult OwnedCall(SemaRef.Owned(TheCall));
-
-  // Type-check the __builtin_shufflevector expression.
-  OwningExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall);
-  if (Result.isInvalid())
-    return SemaRef.ExprError();
-
-  OwnedCall.release();
-  return move(Result);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitChooseExpr(ChooseExpr *E) {
-  OwningExprResult Cond = Visit(E->getCond());
-  if (Cond.isInvalid())
-    return SemaRef.ExprError();
-
-  OwningExprResult LHS = SemaRef.InstantiateExpr(E->getLHS(), TemplateArgs);
-  if (LHS.isInvalid())
-    return SemaRef.ExprError();
-
-  OwningExprResult RHS = Visit(E->getRHS());
-  if (RHS.isInvalid())
-    return SemaRef.ExprError();
-
-  return SemaRef.ActOnChooseExpr(E->getBuiltinLoc(),
-                                 move(Cond), move(LHS), move(RHS),
-                                 E->getRParenLoc());
-}
-
-Sema::OwningExprResult TemplateExprInstantiator::VisitVAArgExpr(VAArgExpr *E) {
-  OwningExprResult SubExpr = Visit(E->getSubExpr());
-  if (SubExpr.isInvalid())
-    return SemaRef.ExprError();
-
-  SourceLocation FakeTypeLoc 
-    = SemaRef.PP.getLocForEndOfToken(E->getSubExpr()->getSourceRange()
-                                       .getEnd());
-  QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs,
-                                       /*FIXME:*/FakeTypeLoc, 
-                                       DeclarationName());
-  if (T.isNull())
-    return SemaRef.ExprError();
-
-  return SemaRef.ActOnVAArg(E->getBuiltinLoc(), move(SubExpr),
-                            T.getAsOpaquePtr(), E->getRParenLoc());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitInitListExpr(InitListExpr *E) {
-  ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
-  for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) {
-    OwningExprResult Init = Visit(E->getInit(I));
-    if (Init.isInvalid())
-      return SemaRef.ExprError();
-    Inits.push_back(Init.takeAs<Expr>());
-  }
-
-  return SemaRef.ActOnInitList(E->getLBraceLoc(), move_arg(Inits),
-                               E->getRBraceLoc());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitParenListExpr(ParenListExpr *E) {
-  ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
-  for (unsigned I = 0, N = E->getNumExprs(); I != N; ++I) {
-    OwningExprResult Init = Visit(E->getExpr(I));
-    if (Init.isInvalid())
-      return SemaRef.ExprError();
-    Inits.push_back(Init.takeAs<Expr>());
-  }
-
-  return SemaRef.ActOnParenListExpr(E->getLParenLoc(), E->getRParenLoc(),
-                                    move_arg(Inits));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
-  Designation Desig;
-
-  // Instantiate the initializer value
-  OwningExprResult Init = Visit(E->getInit());
-  if (Init.isInvalid())
-    return SemaRef.ExprError();
-
-  // Instantiate the designators.
-  ASTOwningVector<&ActionBase::DeleteExpr, 4> ArrayExprs(SemaRef);
-  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()) {
-      OwningExprResult Index = Visit(E->getArrayIndex(*D));
-      if (Index.isInvalid())
-        return SemaRef.ExprError();
-
-      Desig.AddDesignator(Designator::getArray(Index.get(), 
-                                               D->getLBracketLoc()));
-
-      ArrayExprs.push_back(Index.release());
-      continue;
-    }
-
-    assert(D->isArrayRangeDesignator() && "New kind of designator?");
-    OwningExprResult Start = Visit(E->getArrayRangeStart(*D));
-    if (Start.isInvalid())
-      return SemaRef.ExprError();
-
-    OwningExprResult End = Visit(E->getArrayRangeEnd(*D));
-    if (End.isInvalid())
-      return SemaRef.ExprError();
-
-    Desig.AddDesignator(Designator::getArrayRange(Start.get(), 
-                                                  End.get(),
-                                                  D->getLBracketLoc(),
-                                                  D->getEllipsisLoc()));
-    
-    ArrayExprs.push_back(Start.release());
-    ArrayExprs.push_back(End.release());
-  }
-
-  OwningExprResult Result = 
-    SemaRef.ActOnDesignatedInitializer(Desig,
-                                       E->getEqualOrColonLoc(),
-                                       E->usesGNUSyntax(),
-                                       move(Init));
-  if (Result.isInvalid())
-    return SemaRef.ExprError();
-
-  ArrayExprs.take();
-  return move(Result);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitImplicitValueInitExpr(
-                                                  ImplicitValueInitExpr *E) {
-  assert(!E->isTypeDependent() && !E->isValueDependent() &&
-         "ImplicitValueInitExprs are never dependent");
-  E->Retain();
-  return SemaRef.Owned(E);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
-  OwningExprResult Base = Visit(E->getBase());
-  if (Base.isInvalid())
-    return SemaRef.ExprError();
-
-  SourceLocation FakeOperatorLoc = 
-    SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
-  return SemaRef.ActOnMemberReferenceExpr(/*Scope=*/0,
-                                          move(Base), 
-                                          /*FIXME*/FakeOperatorLoc,
-                                          tok::period,
-                                          E->getAccessorLoc(),
-                                          E->getAccessor(),
-                                   /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitBlockExpr(BlockExpr *E) {
-  assert(false && "FIXME:Template instantiation for blocks is unimplemented");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
-  assert(false && "FIXME:Template instantiation for blocks is unimplemented");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
-  bool isSizeOf = E->isSizeOf();
-
-  if (E->isArgumentType()) {
-    QualType T = E->getArgumentType();
-    if (T->isDependentType()) {
-      T = SemaRef.InstantiateType(T, TemplateArgs, 
-                                  /*FIXME*/E->getOperatorLoc(),
-                                &SemaRef.PP.getIdentifierTable().get("sizeof"));
-      if (T.isNull())
-        return SemaRef.ExprError();
-    }
-
-    return SemaRef.CreateSizeOfAlignOfExpr(T, E->getOperatorLoc(), isSizeOf,
-                                           E->getSourceRange());
-  } 
-
-  Sema::OwningExprResult Arg(SemaRef);
-  {   
-    // C++0x [expr.sizeof]p1:
-    //   The operand is either an expression, which is an unevaluated operand
-    //   [...]
-    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
-    
-    Arg = Visit(E->getArgumentExpr());
-    if (Arg.isInvalid())
-      return SemaRef.ExprError();
-  }
-
-  Sema::OwningExprResult Result
-    = SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(),
-                                      isSizeOf, E->getSourceRange());
-  if (Result.isInvalid())
-    return SemaRef.ExprError();
-
-  Arg.release();
-  return move(Result);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E) {
-  NestedNameSpecifier *NNS 
-    = SemaRef.InstantiateNestedNameSpecifier(E->getQualifier(), 
-                                             E->getQualifierRange(),
-                                             TemplateArgs);
-  if (!NNS)
-    return SemaRef.ExprError();
-
-  CXXScopeSpec SS;
-  SS.setRange(E->getQualifierRange());
-  SS.setScopeRep(NNS);
-
-  // FIXME: We're passing in a NULL scope, because
-  // ActOnDeclarationNameExpr doesn't actually use the scope when we
-  // give it a non-empty scope specifier. Investigate whether it would
-  // be better to refactor ActOnDeclarationNameExpr.
-  return SemaRef.ActOnDeclarationNameExpr(/*Scope=*/0, E->getLocation(), 
-                                          E->getDeclName(), 
-                                          /*HasTrailingLParen=*/false,
-                                          &SS,
-                                          E->isAddressOfOperand());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXTemporaryObjectExpr(
-                                                  CXXTemporaryObjectExpr *E) {
-  QualType T = E->getType();
-  if (T->isDependentType()) {
-    T = SemaRef.InstantiateType(T, TemplateArgs,
-                                E->getTypeBeginLoc(), DeclarationName());
-    if (T.isNull())
-      return SemaRef.ExprError();
-  }
-
-  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
-  Args.reserve(E->getNumArgs());
-  for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(), 
-                                         ArgEnd = E->arg_end();
-       Arg != ArgEnd; ++Arg) {
-    OwningExprResult InstantiatedArg = Visit(*Arg);
-    if (InstantiatedArg.isInvalid())
-      return SemaRef.ExprError();
-
-    Args.push_back((Expr *)InstantiatedArg.release());
-  }
-
-  SourceLocation CommaLoc;
-  // FIXME: HACK!
-  if (Args.size() > 1) {
-    Expr *First = (Expr *)Args[0];
-    CommaLoc 
-      = SemaRef.PP.getLocForEndOfToken(First->getSourceRange().getEnd());
-  }
-  return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()
-                                                       /*, FIXME*/),
-                                           T.getAsOpaquePtr(),
-                                           /*FIXME*/E->getTypeBeginLoc(),
-                                           move_arg(Args),
-                                           /*HACK*/&CommaLoc,
-                                           E->getSourceRange().getEnd());
-}
-
-Sema::OwningExprResult TemplateExprInstantiator::VisitCastExpr(CastExpr *E) {
-  assert(false && "Cannot instantiate abstract CastExpr");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult TemplateExprInstantiator::VisitImplicitCastExpr(
-                                                         ImplicitCastExpr *E) {
-  assert(!E->isTypeDependent() && "Implicit casts must have known types");
-
-  Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
-  if (SubExpr.isInvalid())
-    return SemaRef.ExprError();
-
-  ImplicitCastExpr *ICE = 
-    new (SemaRef.Context) ImplicitCastExpr(E->getType(),
-                                           E->getCastKind(),
-                                           (Expr *)SubExpr.release(),
-                                           E->isLvalueCast());
-  return SemaRef.Owned(ICE);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitExplicitCastExpr(ExplicitCastExpr *E) {
-  assert(false && "Cannot instantiate abstract ExplicitCastExpr");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCStyleCastExpr(CStyleCastExpr *E) {
-  // Instantiate the type that we're casting to.
-  SourceLocation TypeStartLoc 
-    = SemaRef.PP.getLocForEndOfToken(E->getLParenLoc());
-  QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(),
-                                                TemplateArgs,
-                                                TypeStartLoc,
-                                                DeclarationName());
-  if (ExplicitTy.isNull())
-    return SemaRef.ExprError();
-
-  // Instantiate the subexpression.
-  OwningExprResult SubExpr = Visit(E->getSubExpr());
-  if (SubExpr.isInvalid())
-    return SemaRef.ExprError();
-  
-  return SemaRef.ActOnCastExpr(/*Scope=*/0, E->getLParenLoc(), 
-                               ExplicitTy.getAsOpaquePtr(),
-                               E->getRParenLoc(),
-                               move(SubExpr));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
-  return VisitCallExpr(E);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
-  // Figure out which cast operator we're dealing with.
-  tok::TokenKind Kind;
-  switch (E->getStmtClass()) {
-  case Stmt::CXXStaticCastExprClass:
-    Kind = tok::kw_static_cast;
-    break;
-
-  case Stmt::CXXDynamicCastExprClass:
-    Kind = tok::kw_dynamic_cast;
-    break;
-
-  case Stmt::CXXReinterpretCastExprClass:
-    Kind = tok::kw_reinterpret_cast;
-    break;
-
-  case Stmt::CXXConstCastExprClass:
-    Kind = tok::kw_const_cast;
-    break;
-
-  default:
-    assert(false && "Invalid C++ named cast");
-    return SemaRef.ExprError();
-  }
-
-  // Instantiate the type that we're casting to.
-  SourceLocation TypeStartLoc 
-    = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
-  QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(),
-                                                TemplateArgs,
-                                                TypeStartLoc,
-                                                DeclarationName());
-  if (ExplicitTy.isNull())
-    return SemaRef.ExprError();
-
-  // Instantiate the subexpression.
-  OwningExprResult SubExpr = Visit(E->getSubExpr());
-  if (SubExpr.isInvalid())
-    return SemaRef.ExprError();
-  
-  SourceLocation FakeLAngleLoc 
-    = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
-  SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin();
-  SourceLocation FakeRParenLoc
-    = SemaRef.PP.getLocForEndOfToken(
-                                E->getSubExpr()->getSourceRange().getEnd());
-  return SemaRef.ActOnCXXNamedCast(E->getOperatorLoc(), Kind,
-                                   /*FIXME:*/FakeLAngleLoc,
-                                   ExplicitTy.getAsOpaquePtr(),
-                                   /*FIXME:*/FakeRAngleLoc,
-                                   /*FIXME:*/FakeRAngleLoc,
-                                   move(SubExpr),
-                                   /*FIXME:*/FakeRParenLoc);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
-  return VisitCXXNamedCastExpr(E);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
-  return VisitCXXNamedCastExpr(E);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXReinterpretCastExpr(
-                                                CXXReinterpretCastExpr *E) {
-  return VisitCXXNamedCastExpr(E);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
-  return VisitCXXNamedCastExpr(E);
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitCXXThisExpr(CXXThisExpr *E) {
-  QualType ThisType = 
-    cast<CXXMethodDecl>(SemaRef.CurContext)->getThisType(SemaRef.Context);
-    
-  CXXThisExpr *TE = 
-    new (SemaRef.Context) CXXThisExpr(E->getLocStart(), ThisType);
-  
-  return SemaRef.Owned(TE);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
-  if (E->isTypeOperand()) {
-    QualType T = SemaRef.InstantiateType(E->getTypeOperand(),
-                                         TemplateArgs,
-                                     /*FIXME*/E->getSourceRange().getBegin(),
-                                         DeclarationName());
-    if (T.isNull())
-      return SemaRef.ExprError();
-
-    return SemaRef.ActOnCXXTypeid(E->getSourceRange().getBegin(),
-                                  /*FIXME*/E->getSourceRange().getBegin(),
-                                  true, T.getAsOpaquePtr(),
-                                  E->getSourceRange().getEnd());
-  }
-
-  // We don't know whether the expression is potentially evaluated until
-  // after we perform semantic analysis, so the expression is potentially
-  // potentially evaluated.
-  EnterExpressionEvaluationContext Unevaluated(SemaRef, 
-                                     Action::PotentiallyPotentiallyEvaluated);
-
-  OwningExprResult Operand = Visit(E->getExprOperand());
-  if (Operand.isInvalid())
-    return SemaRef.ExprError();
-
-  OwningExprResult Result 
-    = SemaRef.ActOnCXXTypeid(E->getSourceRange().getBegin(),
-                              /*FIXME*/E->getSourceRange().getBegin(),
-                             false, Operand.get(),
-                             E->getSourceRange().getEnd());
-  if (Result.isInvalid())
-    return SemaRef.ExprError();
-
-  Operand.release(); // FIXME: since ActOnCXXTypeid silently took ownership
-  return move(Result);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXThrowExpr(CXXThrowExpr *E) {
-  OwningExprResult SubExpr(SemaRef, (void *)0);
-  if (E->getSubExpr()) {
-    SubExpr = Visit(E->getSubExpr());
-    if (SubExpr.isInvalid())
-      return SemaRef.ExprError();
-  }
-
-  return SemaRef.ActOnCXXThrow(E->getThrowLoc(), move(SubExpr));
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
-  assert(false && 
-         "FIXME: Instantiation for default arguments is unimplemented");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXBindTemporaryExpr(
-                                                  CXXBindTemporaryExpr *E) {
-  OwningExprResult SubExpr = Visit(E->getSubExpr());
-  if (SubExpr.isInvalid())
-    return SemaRef.ExprError();
-
-  return SemaRef.MaybeBindToTemporary(SubExpr.takeAs<Expr>());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXConstructExpr(CXXConstructExpr *E) {
-  assert(!cast<CXXRecordDecl>(E->getConstructor()->getDeclContext())
-           ->isDependentType() && "Dependent constructor shouldn't be here");
-
-  QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs,
-                                       /*FIXME*/E->getSourceRange().getBegin(),
-                                       DeclarationName());
-  if (T.isNull())
-    return SemaRef.ExprError();
-
-  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
-  for (CXXConstructExpr::arg_iterator Arg = E->arg_begin(), 
-                                   ArgEnd = E->arg_end();
-       Arg != ArgEnd; ++Arg) {
-    OwningExprResult ArgInst = Visit(*Arg);
-    if (ArgInst.isInvalid())
-      return SemaRef.ExprError();
-
-    Args.push_back(ArgInst.takeAs<Expr>());
-  }
-
-  return SemaRef.Owned(SemaRef.BuildCXXConstructExpr(SemaRef.Context, T,
-                                             E->getConstructor(), 
-                                             E->isElidable(),
-                                             Args.takeAs<Expr>(), 
-                                             Args.size()));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXFunctionalCastExpr(
-                                                   CXXFunctionalCastExpr *E) {
-  // Instantiate the type that we're casting to.
-  QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(),
-                                                TemplateArgs,
-                                                E->getTypeBeginLoc(),
-                                                DeclarationName());
-  if (ExplicitTy.isNull())
-    return SemaRef.ExprError();
-
-  // Instantiate the subexpression.
-  OwningExprResult SubExpr = Visit(E->getSubExpr());
-  if (SubExpr.isInvalid())
-    return SemaRef.ExprError();
-  
-  // FIXME: The end of the type's source range is wrong
-  Expr *Sub = SubExpr.takeAs<Expr>();
-  return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()),
-                                           ExplicitTy.getAsOpaquePtr(),
-                                           /*FIXME:*/E->getTypeBeginLoc(),
-                                           Sema::MultiExprArg(SemaRef,
-                                                              (void **)&Sub,
-                                                              1),
-                                           0, 
-                                           E->getRParenLoc());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXNewExpr(CXXNewExpr *E) {
-  // Instantiate the type that we're allocating
-  QualType AllocType = SemaRef.InstantiateType(E->getAllocatedType(),
-                                               TemplateArgs,
-                                   /*FIXME:*/E->getSourceRange().getBegin(),
-                                               DeclarationName());
-  if (AllocType.isNull())
-    return SemaRef.ExprError();
-
-  // Instantiate the size of the array we're allocating (if any).
-  OwningExprResult ArraySize = SemaRef.InstantiateExpr(E->getArraySize(),
-                                                       TemplateArgs);
-  if (ArraySize.isInvalid())
-    return SemaRef.ExprError();
-
-  // Instantiate the placement arguments (if any).
-  ASTOwningVector<&ActionBase::DeleteExpr> PlacementArgs(SemaRef);
-  for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
-    OwningExprResult Arg = Visit(E->getPlacementArg(I));
-    if (Arg.isInvalid())
-      return SemaRef.ExprError();
-
-    PlacementArgs.push_back(Arg.take());
-  }
-
-  // Instantiate the constructor arguments (if any).
-  ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(SemaRef);
-  for (unsigned I = 0, N = E->getNumConstructorArgs(); I != N; ++I) {
-    OwningExprResult Arg = Visit(E->getConstructorArg(I));
-    if (Arg.isInvalid())
-      return SemaRef.ExprError();
-
-    ConstructorArgs.push_back(Arg.take());
-  }
-
-  return SemaRef.BuildCXXNew(E->getSourceRange().getBegin(), 
-                             E->isGlobalNew(),
-                             /*FIXME*/SourceLocation(),
-                             move_arg(PlacementArgs),
-                             /*FIXME*/SourceLocation(),
-                             E->isParenTypeId(),
-                             AllocType,
-                             /*FIXME*/E->getSourceRange().getBegin(),
-                             SourceRange(),
-                             move(ArraySize),
-                             /*FIXME*/SourceLocation(),
-                             Sema::MultiExprArg(SemaRef,
-                                                ConstructorArgs.take(),
-                                                ConstructorArgs.size()),
-                             E->getSourceRange().getEnd());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
-  OwningExprResult Operand = Visit(E->getArgument());
-  if (Operand.isInvalid())
-    return SemaRef.ExprError();
-
-  return SemaRef.ActOnCXXDelete(E->getSourceRange().getBegin(),
-                                E->isGlobalDelete(),
-                                E->isArrayForm(),
-                                move(Operand));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
-  QualType T = SemaRef.InstantiateType(E->getQueriedType(), TemplateArgs,
-                                       /*FIXME*/E->getSourceRange().getBegin(),
-                                       DeclarationName());
-  if (T.isNull())
-    return SemaRef.ExprError();
-
-  SourceLocation FakeLParenLoc
-    = SemaRef.PP.getLocForEndOfToken(E->getSourceRange().getBegin());
-  return SemaRef.ActOnUnaryTypeTrait(E->getTrait(),
-                                     E->getSourceRange().getBegin(),
-                                     /*FIXME*/FakeLParenLoc,
-                                     T.getAsOpaquePtr(),
-                                     E->getSourceRange().getEnd());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *E) {
-  NestedNameSpecifier *NNS 
-    = SemaRef.InstantiateNestedNameSpecifier(E->getQualifier(),
-                                             E->getQualifierRange(),
-                                             TemplateArgs);
-  if (!NNS)
-    return SemaRef.ExprError();
-
-  CXXScopeSpec SS;
-  SS.setRange(E->getQualifierRange());
-  SS.setScopeRep(NNS);
-  return SemaRef.ActOnDeclarationNameExpr(/*Scope=*/0, 
-                                          E->getLocation(),
-                                          E->getDecl()->getDeclName(),
-                                          /*Trailing lparen=*/false,
-                                          &SS,
-                                          /*FIXME:*/false);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXExprWithTemporaries(
-                                                  CXXExprWithTemporaries *E) {
-  OwningExprResult SubExpr = Visit(E->getSubExpr());
-  if (SubExpr.isInvalid())
-    return SemaRef.ExprError();
-
-  Expr *Temp = 
-    SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>(),
-                                              E->shouldDestroyTemporaries());
-  return SemaRef.Owned(Temp);
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXUnresolvedConstructExpr(
-                                              CXXUnresolvedConstructExpr *E) {
-  QualType T = SemaRef.InstantiateType(E->getTypeAsWritten(), TemplateArgs,
-                                       E->getTypeBeginLoc(), 
-                                       DeclarationName());
-  if (T.isNull())
-    return SemaRef.ExprError();
-
-  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
-  llvm::SmallVector<SourceLocation, 8> FakeCommaLocs;
-  for (CXXUnresolvedConstructExpr::arg_iterator Arg = E->arg_begin(),
-                                             ArgEnd = E->arg_end();
-       Arg != ArgEnd; ++Arg) {
-    OwningExprResult InstArg = Visit(*Arg);
-    if (InstArg.isInvalid())
-      return SemaRef.ExprError();
-
-    FakeCommaLocs.push_back(
-           SemaRef.PP.getLocForEndOfToken((*Arg)->getSourceRange().getEnd()));
-    Args.push_back(InstArg.takeAs<Expr>());
-  }
-
-  // FIXME: The end of the type range isn't exactly correct.
-  // FIXME: we're faking the locations of the commas
-  return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc(),
-                                                       E->getLParenLoc()),
-                                           T.getAsOpaquePtr(),
-                                           E->getLParenLoc(),
-                                           move_arg(Args),
-                                           &FakeCommaLocs.front(),
-                                           E->getRParenLoc());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitCXXUnresolvedMemberExpr(
-                                                 CXXUnresolvedMemberExpr *E) {
-  // Instantiate the base of the expression.
-  OwningExprResult Base = Visit(E->getBase());
-  if (Base.isInvalid())
-    return SemaRef.ExprError();
-
-  tok::TokenKind OpKind = E->isArrow() ? tok::arrow : tok::period;
-  CXXScopeSpec SS;
-  Base = SemaRef.ActOnCXXEnterMemberScope(0, SS, move(Base), OpKind);
-  // FIXME: Instantiate the declaration name.
-  Base = SemaRef.ActOnMemberReferenceExpr(/*Scope=*/0,
-                                          move(Base), E->getOperatorLoc(),
-                                          OpKind,
-                                          E->getMemberLoc(),
-                              /*FIXME:*/*E->getMember().getAsIdentifierInfo(),
-                              /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
-  SemaRef.ActOnCXXExitMemberScope(0, SS);
-  return move(Base);
-}
-
-//----------------------------------------------------------------------------
-// Objective-C Expressions
-//----------------------------------------------------------------------------
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCStringLiteral(ObjCStringLiteral *E) {
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
-  QualType EncodedType = SemaRef.InstantiateType(E->getEncodedType(),
-                                                 TemplateArgs,
-                                                 /*FIXME:*/E->getAtLoc(),
-                                                 DeclarationName());
-  if (EncodedType.isNull())
-    return SemaRef.ExprError();
-  
-  return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(E->getAtLoc(), 
-                                                         EncodedType, 
-                                                         E->getRParenLoc()));
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCMessageExpr(ObjCMessageExpr *E) { 
-  assert(false && "FIXME: Template instantiations for ObjC expressions");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { 
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { 
-  return SemaRef.Owned(E->Retain());
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { 
-  assert(false && "FIXME: Template instantiations for ObjC expressions");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { 
-  assert(false && "FIXME: Template instantiations for ObjC expressions");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { 
-  assert(false && "FIXME: Template instantiations for ObjC expressions");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCSuperExpr(ObjCSuperExpr *E) { 
-  assert(false && "FIXME: Template instantiations for ObjC expressions");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-TemplateExprInstantiator::VisitObjCIsaExpr(ObjCIsaExpr *E) { 
-  assert(false && "FIXME: Template instantiations for ObjC expressions");
-  return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult 
-Sema::InstantiateExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
-  if (!E)
-    return Owned((Expr *)0);
-
-  TemplateExprInstantiator Instantiator(*this, TemplateArgs);
-  return Instantiator.Visit(E);
-}

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=78645&r1=78644&r2=78645&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Aug 11 00:31:07 2009
@@ -16,6 +16,11 @@
 #include "Sema.h"
 #include "clang/Sema/SemaDiagnostic.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Parse/Ownership.h"
+#include "clang/Parse/Designator.h"
+#include "clang/Lex/Preprocessor.h"
 #include <algorithm>
 
 namespace clang {
@@ -80,6 +85,12 @@
   Sema &SemaRef;
   
 public:  
+  typedef Sema::OwningStmtResult OwningStmtResult;
+  typedef Sema::OwningExprResult OwningExprResult;
+  typedef Sema::StmtArg StmtArg;
+  typedef Sema::ExprArg ExprArg;
+  typedef Sema::MultiExprArg MultiExprArg;
+  
   /// \brief Initializes a new tree transformer.
   TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
           
@@ -117,6 +128,34 @@
   /// 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();
+      Self.getDerived().setBase(Location, Entity);
+    }
+    
+    ~TemporaryBase() {
+      Self.getDerived().setBase(OldLocation, OldEntity);
+    }
+  };
+  
   /// \brief Determine whether the given type \p T has already been 
   /// transformed.
   ///
@@ -153,14 +192,29 @@
   /// \brief Transform the given statement.
   ///
   /// FIXME: At the moment, subclasses must override this.
-  Sema::OwningStmtResult TransformStmt(Stmt *S);
+  OwningStmtResult TransformStmt(Stmt *S);
   
   /// \brief Transform the given expression.
   ///
-  /// By default, invokes the derived class's TransformStmt() and downcasts
-  /// the result. Subclasses may override this function to provide alternate
-  /// behavior.
-  Sema::OwningExprResult TransformExpr(Expr *E);
+  /// 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.
+  OwningExprResult TransformExpr(Expr *E) {
+    return getDerived().TransformExpr(E, /*isAddressOfOperand=*/false);
+  }
+
+  /// \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.
+  OwningExprResult TransformExpr(Expr *E, bool isAddressOfOperand);
   
   /// \brief Transform the given declaration, which is referenced from a type
   /// or expression.
@@ -197,6 +251,17 @@
   QualType Transform##CLASS##Type(const CLASS##Type *T);
 #include "clang/AST/TypeNodes.def"      
 
+  OwningStmtResult TransformCompoundStmt(Stmt *S, bool IsStmtExpr) {
+    // FIXME: Actually handle this transformation properly.
+    return getDerived().TransformStmt(S);
+  }
+                                         
+#define STMT(Node, Parent)
+#define EXPR(Node, Parent)                        \
+  OwningExprResult Transform##Node(Node *E);
+#define ABSTRACT_EXPR(Node, Parent)
+#include "clang/AST/StmtNodes.def"
+  
   /// \brief Build a new pointer type given its pointee type.
   ///
   /// By default, performs semantic analysis when building the pointer type.
@@ -291,7 +356,7 @@
   /// Subclasses may override this routine to provide different behavior.
   QualType RebuildVariableArrayType(QualType ElementType, 
                                     ArrayType::ArraySizeModifier SizeMod,
-                                    Sema::ExprArg SizeExpr,
+                                    ExprArg SizeExpr,
                                     unsigned IndexTypeQuals,
                                     SourceRange BracketsRange);
 
@@ -302,7 +367,7 @@
   /// Subclasses may override this routine to provide different behavior.
   QualType RebuildDependentSizedArrayType(QualType ElementType, 
                                           ArrayType::ArraySizeModifier SizeMod,
-                                          Sema::ExprArg SizeExpr,
+                                          ExprArg SizeExpr,
                                           unsigned IndexTypeQuals,
                                           SourceRange BracketsRange);
 
@@ -327,7 +392,7 @@
   /// By default, performs semantic analysis when building the vector type.
   /// Subclasses may override this routine to provide different behavior.
   QualType RebuildDependentSizedExtVectorType(QualType ElementType, 
-                                              Sema::ExprArg SizeExpr,
+                                              ExprArg SizeExpr,
                                               SourceLocation AttributeLoc);
     
   /// \brief Build a new function type.
@@ -358,7 +423,7 @@
   ///
   /// By default, performs semantic analysis when building the typeof type.
   /// Subclasses may override this routine to provide different behavior.
-  QualType RebuildTypeOfExprType(Sema::ExprArg Underlying);
+  QualType RebuildTypeOfExprType(ExprArg Underlying);
 
   /// \brief Build a new typeof(type) type. 
   ///
@@ -369,7 +434,7 @@
   ///
   /// By default, performs semantic analysis when building the decltype type.
   /// Subclasses may override this routine to provide different behavior.
-  QualType RebuildDecltypeType(Sema::ExprArg Underlying);
+  QualType RebuildDecltypeType(ExprArg Underlying);
   
   /// \brief Build a new template specialization type.
   ///
@@ -473,15 +538,795 @@
   /// behavior.
   TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
                                    const IdentifierInfo &II);
+  
+  
+  /// \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.
+  OwningExprResult RebuildDeclRefExpr(NamedDecl *ND, SourceLocation Loc) {
+    return getSema().BuildDeclarationNameExpr(Loc, ND,
+                                              /*FIXME:*/false,
+                                              /*SS=*/0,
+                                              /*FIXME:*/false);
+  }
+  
+  /// \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.
+  OwningExprResult RebuildParenExpr(ExprArg SubExpr, SourceLocation LParen,
+                                    SourceLocation RParen) {
+    return getSema().ActOnParenExpr(LParen, RParen, move(SubExpr));
+  }
+
+  /// \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.
+  OwningExprResult RebuildUnaryOperator(SourceLocation OpLoc,
+                                        UnaryOperator::Opcode Opc,
+                                        ExprArg SubExpr) {
+    return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, move(SubExpr));
+  }
+  
+  /// \brief Build a new sizeof or alignof expression with a type argument.
+  /// 
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildSizeOfAlignOf(QualType T, SourceLocation OpLoc,
+                                        bool isSizeOf, SourceRange R) {
+    return getSema().CreateSizeOfAlignOfExpr(T, OpLoc, isSizeOf, R);
+  }
+
+  /// \brief Build a new sizeof or alignof expression with an expression 
+  /// argument.
+  /// 
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildSizeOfAlignOf(ExprArg SubExpr, SourceLocation OpLoc,
+                                        bool isSizeOf, SourceRange R) {
+    OwningExprResult Result 
+      = getSema().CreateSizeOfAlignOfExpr((Expr *)SubExpr.get(),
+                                          OpLoc, isSizeOf, R);
+    if (Result.isInvalid())
+      return getSema().ExprError();
+    
+    SubExpr.release();
+    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.
+  OwningExprResult RebuildArraySubscriptExpr(ExprArg LHS, 
+                                             SourceLocation LBracketLoc,
+                                             ExprArg RHS,
+                                             SourceLocation RBracketLoc) {
+    return getSema().ActOnArraySubscriptExpr(/*Scope=*/0, move(LHS),
+                                             LBracketLoc, move(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.
+  OwningExprResult RebuildCallExpr(ExprArg Callee, SourceLocation LParenLoc,
+                                   MultiExprArg Args,
+                                   SourceLocation *CommaLocs,
+                                   SourceLocation RParenLoc) {
+    return getSema().ActOnCallExpr(/*Scope=*/0, move(Callee), LParenLoc,
+                                   move(Args), CommaLocs, RParenLoc);
+  }
+
+  /// \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.
+  OwningExprResult RebuildMemberExpr(ExprArg Base, SourceLocation OpLoc,
+                                     bool isArrow, SourceLocation MemberLoc,
+                                     NamedDecl *Member) {
+    return getSema().ActOnMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
+                                              isArrow? tok::arrow : tok::period,
+                                              MemberLoc,
+                                              /*FIXME*/*Member->getIdentifier(),
+                                     /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
+  }
+  
+  /// \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.
+  OwningExprResult RebuildBinaryOperator(SourceLocation OpLoc,
+                                         BinaryOperator::Opcode Opc,
+                                         ExprArg LHS, ExprArg RHS) {
+    OwningExprResult Result
+      = getSema().CreateBuiltinBinOp(OpLoc, Opc, (Expr *)LHS.get(), 
+                                     (Expr *)RHS.get());
+    if (Result.isInvalid())
+      return SemaRef.ExprError();
+    
+    LHS.release();
+    RHS.release();
+    return move(Result);
+  }
+
+  /// \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.
+  OwningExprResult RebuildConditionalOperator(ExprArg Cond,
+                                              SourceLocation QuestionLoc,
+                                              ExprArg LHS,
+                                              SourceLocation ColonLoc,
+                                              ExprArg RHS) {
+    return getSema().ActOnConditionalOp(QuestionLoc, ColonLoc, move(Cond), 
+                                        move(LHS), move(RHS));
+  }
+
+  /// \brief Build a new implicit cast expression.
+  /// 
+  /// By default, builds a new implicit cast without any semantic analysis.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildImplicitCastExpr(QualType T, CastExpr::CastKind Kind,
+                                           ExprArg SubExpr, bool isLvalue) {
+    ImplicitCastExpr *ICE
+      = new (getSema().Context) ImplicitCastExpr(T, Kind, 
+                                                 (Expr *)SubExpr.release(),
+                                                 isLvalue);
+    return getSema().Owned(ICE);
+  }
+
+  /// \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.
+  OwningExprResult RebuildCStyleCaseExpr(SourceLocation LParenLoc,
+                                         QualType ExplicitTy,
+                                         SourceLocation RParenLoc,
+                                         ExprArg SubExpr) {
+    return getSema().ActOnCastExpr(/*Scope=*/0,
+                                   LParenLoc,
+                                   ExplicitTy.getAsOpaquePtr(),
+                                   RParenLoc,
+                                   move(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.
+  OwningExprResult RebuildCompoundLiteralExpr(SourceLocation LParenLoc,
+                                              QualType T,
+                                              SourceLocation RParenLoc,
+                                              ExprArg Init) {
+    return getSema().ActOnCompoundLiteral(LParenLoc, T.getAsOpaquePtr(),
+                                          RParenLoc, move(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.
+  OwningExprResult RebuildExtVectorElementExpr(ExprArg Base, 
+                                               SourceLocation OpLoc,
+                                               SourceLocation AccessorLoc,
+                                               IdentifierInfo &Accessor) {
+    return getSema().ActOnMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
+                                              tok::period, AccessorLoc,
+                                              Accessor,
+                                     /*FIXME?*/Sema::DeclPtrTy::make((Decl*)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.
+  OwningExprResult RebuildInitList(SourceLocation LBraceLoc,
+                                   MultiExprArg Inits,
+                                   SourceLocation RBraceLoc) {
+    return SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc);
+  }
+  
+  /// \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.
+  OwningExprResult RebuildDesignatedInitExpr(Designation &Desig,
+                                             MultiExprArg ArrayExprs,
+                                             SourceLocation EqualOrColonLoc,
+                                             bool GNUSyntax,
+                                             ExprArg Init) {
+    OwningExprResult Result
+      = SemaRef.ActOnDesignatedInitializer(Desig, EqualOrColonLoc, GNUSyntax,
+                                           move(Init));
+    if (Result.isInvalid())
+      return SemaRef.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.
+  OwningExprResult 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.
+  OwningExprResult RebuildVAArgExpr(SourceLocation BuiltinLoc, ExprArg SubExpr,
+                                    QualType T, SourceLocation RParenLoc) {
+    return getSema().ActOnVAArg(BuiltinLoc, move(SubExpr), T.getAsOpaquePtr(), 
+                                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.
+  OwningExprResult 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.
+  OwningExprResult RebuildAddrLabelExpr(SourceLocation AmpAmpLoc,
+                                        SourceLocation LabelLoc,
+                                        LabelStmt *Label) {
+    return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label->getID());
+  }
+  
+  /// \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.
+  OwningExprResult RebuildStmtExpr(SourceLocation LParenLoc,
+                                   StmtArg SubStmt,
+                                   SourceLocation RParenLoc) {
+    return getSema().ActOnStmtExpr(LParenLoc, move(SubStmt), RParenLoc);
+  }
+  
+  /// \brief Build a new __builtin_types_compatible_p expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildTypesCompatibleExpr(SourceLocation BuiltinLoc,
+                                              QualType T1, QualType T2,
+                                              SourceLocation RParenLoc) {
+    return getSema().ActOnTypesCompatibleExpr(BuiltinLoc,
+                                              T1.getAsOpaquePtr(),
+                                              T2.getAsOpaquePtr(),
+                                              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.
+  OwningExprResult RebuildChooseExpr(SourceLocation BuiltinLoc,
+                                     ExprArg Cond, ExprArg LHS, ExprArg RHS,
+                                     SourceLocation RParenLoc) {
+    return SemaRef.ActOnChooseExpr(BuiltinLoc,
+                                   move(Cond), move(LHS), move(RHS),
+                                   RParenLoc);
+  }
+  
+  /// \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.
+  OwningExprResult RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
+                                              SourceLocation OpLoc,
+                                              ExprArg Callee,
+                                              ExprArg First,
+                                              ExprArg 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.
+  OwningExprResult RebuildCXXNamedCastExpr(SourceLocation OpLoc,
+                                           Stmt::StmtClass Class,
+                                           SourceLocation LAngleLoc,
+                                           QualType T,
+                                           SourceLocation RAngleLoc,
+                                           SourceLocation LParenLoc,
+                                           ExprArg SubExpr,
+                                           SourceLocation RParenLoc) {
+    switch (Class) {
+    case Stmt::CXXStaticCastExprClass:
+      return getDerived().RebuildCXXStaticCastExpr(OpLoc, LAngleLoc, T, 
+                                                   RAngleLoc, LParenLoc, 
+                                                   move(SubExpr), RParenLoc);
+
+    case Stmt::CXXDynamicCastExprClass:
+      return getDerived().RebuildCXXDynamicCastExpr(OpLoc, LAngleLoc, T, 
+                                                    RAngleLoc, LParenLoc, 
+                                                    move(SubExpr), RParenLoc);
+        
+    case Stmt::CXXReinterpretCastExprClass:
+      return getDerived().RebuildCXXReinterpretCastExpr(OpLoc, LAngleLoc, T, 
+                                                        RAngleLoc, LParenLoc, 
+                                                        move(SubExpr), 
+                                                        RParenLoc);
+        
+    case Stmt::CXXConstCastExprClass:
+      return getDerived().RebuildCXXConstCastExpr(OpLoc, LAngleLoc, T, 
+                                                   RAngleLoc, LParenLoc, 
+                                                   move(SubExpr), RParenLoc);
+        
+    default:
+      assert(false && "Invalid C++ named cast");
+      break;
+    }
+    
+    return getSema().ExprError();
+  }
+  
+  /// \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.
+  OwningExprResult RebuildCXXStaticCastExpr(SourceLocation OpLoc,
+                                            SourceLocation LAngleLoc,
+                                            QualType T,
+                                            SourceLocation RAngleLoc,
+                                            SourceLocation LParenLoc,
+                                            ExprArg SubExpr,
+                                            SourceLocation RParenLoc) {
+    return getSema().ActOnCXXNamedCast(OpLoc, tok::kw_static_cast,
+                                       LAngleLoc, T.getAsOpaquePtr(), RAngleLoc, 
+                                       LParenLoc, move(SubExpr), 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.
+  OwningExprResult RebuildCXXDynamicCastExpr(SourceLocation OpLoc,
+                                             SourceLocation LAngleLoc,
+                                             QualType T,
+                                             SourceLocation RAngleLoc,
+                                             SourceLocation LParenLoc,
+                                             ExprArg SubExpr,
+                                             SourceLocation RParenLoc) {
+    return getSema().ActOnCXXNamedCast(OpLoc, tok::kw_dynamic_cast,
+                                       LAngleLoc, T.getAsOpaquePtr(), RAngleLoc, 
+                                       LParenLoc, move(SubExpr), 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.
+  OwningExprResult RebuildCXXReinterpretCastExpr(SourceLocation OpLoc,
+                                                 SourceLocation LAngleLoc,
+                                                 QualType T,
+                                                 SourceLocation RAngleLoc,
+                                                 SourceLocation LParenLoc,
+                                                 ExprArg SubExpr,
+                                                 SourceLocation RParenLoc) {
+    return getSema().ActOnCXXNamedCast(OpLoc, tok::kw_reinterpret_cast,
+                                       LAngleLoc, T.getAsOpaquePtr(), RAngleLoc,
+                                       LParenLoc, move(SubExpr), 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.
+  OwningExprResult RebuildCXXConstCastExpr(SourceLocation OpLoc,
+                                           SourceLocation LAngleLoc,
+                                           QualType T,
+                                           SourceLocation RAngleLoc,
+                                           SourceLocation LParenLoc,
+                                           ExprArg SubExpr,
+                                           SourceLocation RParenLoc) {
+    return getSema().ActOnCXXNamedCast(OpLoc, tok::kw_const_cast,
+                                       LAngleLoc, T.getAsOpaquePtr(), RAngleLoc, 
+                                       LParenLoc, move(SubExpr), 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.
+  OwningExprResult RebuildCXXFunctionalCastExpr(SourceRange TypeRange,
+                                                QualType T,
+                                                SourceLocation LParenLoc,
+                                                ExprArg SubExpr,
+                                                SourceLocation RParenLoc) {
+    Expr *Sub = SubExpr.takeAs<Expr>();
+    return getSema().ActOnCXXTypeConstructExpr(TypeRange,
+                                               T.getAsOpaquePtr(),
+                                               LParenLoc,
+                                               Sema::MultiExprArg(getSema(),
+                                                                  (void **)&Sub,
+                                                                  1),
+                                               /*CommaLocs=*/0, 
+                                               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.
+  OwningExprResult RebuildCXXTypeidExpr(SourceLocation TypeidLoc,
+                                        SourceLocation LParenLoc,
+                                        QualType T,
+                                        SourceLocation RParenLoc) {
+    return getSema().ActOnCXXTypeid(TypeidLoc, LParenLoc, true, 
+                                    T.getAsOpaquePtr(), 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.
+  OwningExprResult RebuildCXXTypeidExpr(SourceLocation TypeidLoc,
+                                        SourceLocation LParenLoc,
+                                        ExprArg Operand,
+                                        SourceLocation RParenLoc) {
+    OwningExprResult Result 
+      = getSema().ActOnCXXTypeid(TypeidLoc, LParenLoc, false, Operand.get(),
+                                 RParenLoc);
+    if (Result.isInvalid())
+      return getSema().ExprError();
+    
+    Operand.release(); // FIXME: since ActOnCXXTypeid silently took ownership
+    return move(Result);
+  }  
+  
+  /// \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.
+  OwningExprResult RebuildCXXThisExpr(SourceLocation ThisLoc, 
+                                      QualType ThisType) {
+    return getSema().Owned(
+                      new (getSema().Context) CXXThisExpr(ThisLoc, ThisType));
+  }
+
+  /// \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.
+  OwningExprResult RebuildCXXThrowExpr(SourceLocation ThrowLoc, ExprArg Sub) {
+    return getSema().ActOnCXXThrow(ThrowLoc, move(Sub));
+  }
+
+  /// \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.
+  OwningExprResult RebuildCXXDefaultArgExpr(ParmVarDecl *Param) {
+    return getSema().Owned(new (getSema().Context) CXXDefaultArgExpr(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.
+  OwningExprResult RebuildCXXZeroInitValueExpr(SourceLocation TypeStartLoc, 
+                                               SourceLocation LParenLoc,
+                                               QualType T,
+                                               SourceLocation RParenLoc) {
+    return getSema().ActOnCXXTypeConstructExpr(SourceRange(TypeStartLoc), 
+                                               T.getAsOpaquePtr(), LParenLoc, 
+                                               MultiExprArg(getSema(), 0, 0), 
+                                               0, RParenLoc);
+  }
+  
+  /// \brief Build a new C++ conditional declaration expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXConditionDeclExpr(SourceLocation StartLoc, 
+                                               SourceLocation EqLoc,
+                                               VarDecl *Var) {
+    return SemaRef.Owned(new (SemaRef.Context) CXXConditionDeclExpr(StartLoc,
+                                                                    EqLoc,
+                                                                    Var));
+  }
+  
+  /// \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.
+  OwningExprResult RebuildCXXNewExpr(SourceLocation StartLoc, 
+                                     bool UseGlobal,
+                                     SourceLocation PlacementLParen,
+                                     MultiExprArg PlacementArgs,
+                                     SourceLocation PlacementRParen,
+                                     bool ParenTypeId, 
+                                     QualType AllocType,
+                                     SourceLocation TypeLoc,
+                                     SourceRange TypeRange,
+                                     ExprArg ArraySize,
+                                     SourceLocation ConstructorLParen,
+                                     MultiExprArg ConstructorArgs,
+                                     SourceLocation ConstructorRParen) {
+    return getSema().BuildCXXNew(StartLoc, UseGlobal, 
+                                 PlacementLParen,
+                                 move(PlacementArgs),
+                                 PlacementRParen,
+                                 ParenTypeId,
+                                 AllocType,
+                                 TypeLoc,
+                                 TypeRange,
+                                 move(ArraySize),
+                                 ConstructorLParen,
+                                 move(ConstructorArgs),
+                                 ConstructorRParen);
+  }
+  
+  /// \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.
+  OwningExprResult RebuildCXXDeleteExpr(SourceLocation StartLoc,
+                                        bool IsGlobalDelete,
+                                        bool IsArrayForm,
+                                        ExprArg Operand) {
+    return getSema().ActOnCXXDelete(StartLoc, IsGlobalDelete, IsArrayForm,
+                                    move(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.
+  OwningExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait,
+                                         SourceLocation StartLoc,
+                                         SourceLocation LParenLoc,
+                                         QualType T,
+                                         SourceLocation RParenLoc) {
+    return getSema().ActOnUnaryTypeTrait(Trait, StartLoc, LParenLoc, 
+                                         T.getAsOpaquePtr(), RParenLoc);
+  }
+
+  /// \brief Build a new qualified declaration reference expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildQualifiedDeclRefExpr(NestedNameSpecifier *NNS,
+                                               SourceRange QualifierRange,
+                                               NamedDecl *ND,
+                                               SourceLocation Location,
+                                               bool IsAddressOfOperand) {
+    CXXScopeSpec SS;
+    SS.setRange(QualifierRange);
+    SS.setScopeRep(NNS);
+    return getSema().ActOnDeclarationNameExpr(/*Scope=*/0, 
+                                              Location,
+                                              ND->getDeclName(),
+                                              /*Trailing lparen=*/false,
+                                              &SS,
+                                              IsAddressOfOperand);
+  }
+
+  /// \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.
+  OwningExprResult RebuildUnresolvedDeclRefExpr(NestedNameSpecifier *NNS,
+                                                SourceRange QualifierRange,
+                                                DeclarationName Name,
+                                                SourceLocation Location,
+                                                bool IsAddressOfOperand) {
+    CXXScopeSpec SS;
+    SS.setRange(QualifierRange);
+    SS.setScopeRep(NNS);
+    return getSema().ActOnDeclarationNameExpr(/*Scope=*/0, 
+                                              Location,
+                                              Name,
+                                              /*Trailing lparen=*/false,
+                                              &SS,
+                                              IsAddressOfOperand);
+  }
+
+  /// \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.
+  OwningExprResult RebuildTemplateIdExpr(TemplateName Template,
+                                         SourceLocation TemplateLoc,
+                                         SourceLocation LAngleLoc,
+                                         TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceLocation RAngleLoc) {
+    return getSema().BuildTemplateIdExpr(Template, TemplateLoc,
+                                         LAngleLoc,
+                                         TemplateArgs, NumTemplateArgs,
+                                         RAngleLoc);
+  }
+
+  /// \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.
+  OwningExprResult RebuildCXXConstructExpr(QualType T,
+                                           CXXConstructorDecl *Constructor,
+                                           bool IsElidable,
+                                           MultiExprArg Args) {
+    unsigned NumArgs = Args.size();
+    Expr **ArgsExprs = (Expr **)Args.release();
+    return getSema().Owned(SemaRef.BuildCXXConstructExpr(getSema().Context, T,
+                                                         Constructor,
+                                                         IsElidable,
+                                                         ArgsExprs,
+                                                         NumArgs));
+  }
+
+  /// \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.
+  OwningExprResult RebuildCXXTemporaryObjectExpr(SourceLocation TypeBeginLoc,
+                                                 QualType T,
+                                                 SourceLocation LParenLoc,
+                                                 MultiExprArg Args,
+                                                 SourceLocation *Commas,
+                                                 SourceLocation RParenLoc) {
+    return getSema().ActOnCXXTypeConstructExpr(SourceRange(TypeBeginLoc),
+                                               T.getAsOpaquePtr(),
+                                               LParenLoc,
+                                               move(Args),
+                                               Commas,
+                                               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.
+  OwningExprResult RebuildCXXUnresolvedConstructExpr(SourceLocation TypeBeginLoc,
+                                                     QualType T,
+                                                     SourceLocation LParenLoc,
+                                                     MultiExprArg Args,
+                                                     SourceLocation *Commas,
+                                                     SourceLocation RParenLoc) {
+    return getSema().ActOnCXXTypeConstructExpr(SourceRange(TypeBeginLoc,
+                                                           /*FIXME*/LParenLoc),
+                                               T.getAsOpaquePtr(),
+                                               LParenLoc,
+                                               move(Args),
+                                               Commas,
+                                               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.
+  OwningExprResult RebuildCXXUnresolvedMemberExpr(ExprArg Base,
+                                                  bool IsArrow,
+                                                  SourceLocation OperatorLoc,
+                                                  DeclarationName Name,
+                                                  SourceLocation MemberLoc) {
+    tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period;
+    CXXScopeSpec SS;
+    Base = SemaRef.ActOnCXXEnterMemberScope(0, SS, move(Base), OpKind);
+    if (Base.isInvalid())
+      return SemaRef.ExprError();
+    
+    assert(Name.getAsIdentifierInfo() && 
+           "Cannot transform member references with non-identifier members");
+    Base = SemaRef.ActOnMemberReferenceExpr(/*Scope=*/0,
+                                            move(Base), OperatorLoc, OpKind,
+                                            MemberLoc, 
+                                            *Name.getAsIdentifierInfo(),
+                                    /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
+    SemaRef.ActOnCXXExitMemberScope(0, SS);
+    return move(Base);
+  }
+
+  /// \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.
+  OwningExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc,
+                                         QualType T,
+                                         SourceLocation RParenLoc) {
+    return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(AtLoc, T,
+                                                           RParenLoc));
+  }    
+
+  /// \brief Build a new Objective-C protocol expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildObjCProtocolExpr(ObjCProtocolDecl *Protocol,
+                                           SourceLocation AtLoc,
+                                           SourceLocation ProtoLoc,
+                                           SourceLocation LParenLoc,
+                                           SourceLocation RParenLoc) {
+    return SemaRef.Owned(SemaRef.ParseObjCProtocolExpression(
+                                              Protocol->getIdentifier(),
+                                                             AtLoc,
+                                                             ProtoLoc,
+                                                             LParenLoc,
+                                                             RParenLoc));                                                             
+  }
+                                           
+  /// \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.
+  OwningExprResult 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);
+    Expr *Callee 
+      = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(),
+                                          BuiltinLoc, false, false);
+    SemaRef.UsualUnaryConversions(Callee);
+    
+    // Build the CallExpr 
+    unsigned NumSubExprs = SubExprs.size();
+    Expr **Subs = (Expr **)SubExprs.release();
+    CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee,
+                                                       Subs, NumSubExprs,
+                                                       Builtin->getResultType(),
+                                                       RParenLoc);
+    OwningExprResult OwnedCall(SemaRef.Owned(TheCall));
+    
+    // Type-check the __builtin_shufflevector expression.
+    OwningExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall);
+    if (Result.isInvalid())
+      return SemaRef.ExprError();
+    
+    OwnedCall.release();
+    return move(Result);    
+  }
 };
+
   
 template<typename Derived>
-Sema::OwningExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
-  Sema::OwningStmtResult Result = getDerived().TransformStmt(E);
-  if (Result.isInvalid())
-    return SemaRef.ExprError();
-  
-  return SemaRef.Owned(cast_or_null<Stmt>(Result.takeAs<Stmt>()));
+Sema::OwningExprResult TreeTransform<Derived>::TransformExpr(Expr *E,
+                                                    bool isAddressOfOperand) {
+  if (!E)
+    return SemaRef.Owned(E);
+
+  switch (E->getStmtClass()) {
+    case Stmt::NoStmtClass: break;
+#define STMT(Node, Parent) case Stmt::Node##Class: break;
+#define EXPR(Node, Parent)                                              \
+    case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E));
+#include "clang/AST/StmtNodes.def"
+  }  
+      
+  return SemaRef.Owned(E->Retain());
 }
 
 template<typename Derived>
@@ -1230,29 +2075,1425 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Type reconstruction
+// Expression transformation
 //===----------------------------------------------------------------------===//
-
 template<typename Derived> 
-QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
-  return SemaRef.BuildPointerType(PointeeType, 0, 
-                                  getDerived().getBaseLocation(),
-                                  getDerived().getBaseEntity());
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) { 
+  return SemaRef.Owned(E->Retain()); 
 }
-
+  
 template<typename Derived> 
-QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
-  return SemaRef.BuildBlockPointerType(PointeeType, 0, 
-                                       getDerived().getBaseLocation(),
-                                       getDerived().getBaseEntity());
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { 
+  NamedDecl *ND 
+    = dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl()));
+  if (!ND)
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() && ND == E->getDecl())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildDeclRefExpr(ND, E->getLocation());
 }
-
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+  
 template<typename Derived> 
-QualType 
-TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
-  return SemaRef.BuildReferenceType(ReferentType, true, 0, 
-                                    getDerived().getBaseLocation(),
-                                    getDerived().getBaseEntity());
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) { 
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildParenExpr(move(SubExpr), E->getLParen(), 
+                                       E->getRParen());
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) { 
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildUnaryOperator(E->getOperatorLoc(),
+                                           E->getOpcode(),
+                                           move(SubExpr));
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { 
+  if (E->isArgumentType()) {
+    QualType T = getDerived().TransformType(E->getArgumentType());
+    if (T.isNull())
+      return SemaRef.ExprError();
+    
+    if (!getDerived().AlwaysRebuild() && T == E->getArgumentType())
+      return SemaRef.Owned(E->Retain());
+    
+    return getDerived().RebuildSizeOfAlignOf(T, E->getOperatorLoc(), 
+                                             E->isSizeOf(), 
+                                             E->getSourceRange());
+  }
+  
+  Sema::OwningExprResult SubExpr(SemaRef);
+  {   
+    // C++0x [expr.sizeof]p1:
+    //   The operand is either an expression, which is an unevaluated operand
+    //   [...]
+    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+    
+    SubExpr = getDerived().TransformExpr(E->getArgumentExpr());
+    if (SubExpr.isInvalid())
+      return SemaRef.ExprError();
+    
+    if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getArgumentExpr())
+      return SemaRef.Owned(E->Retain());
+  }
+  
+  return getDerived().RebuildSizeOfAlignOf(move(SubExpr), E->getOperatorLoc(),
+                                           E->isSizeOf(),
+                                           E->getSourceRange());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
+  OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return SemaRef.ExprError();
+  
+  OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return SemaRef.ExprError();
+  
+  
+  if (!getDerived().AlwaysRebuild() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E->Retain());
+  
+  return getDerived().RebuildArraySubscriptExpr(move(LHS),
+                                           /*FIXME:*/E->getLHS()->getLocStart(),
+                                                move(RHS),
+                                                E->getRBracketLoc());
+}
+  
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
+  // Transform the callee.
+  OwningExprResult Callee = getDerived().TransformExpr(E->getCallee());
+  if (Callee.isInvalid())
+    return SemaRef.ExprError();
+
+  // Transform arguments.
+  bool ArgChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+  llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
+    OwningExprResult Arg = getDerived().TransformExpr(E->getArg(I));
+    if (Arg.isInvalid())
+      return SemaRef.ExprError();
+    
+    // FIXME: Wrong source location information for the ','.
+    FakeCommaLocs.push_back(
+       SemaRef.PP.getLocForEndOfToken(E->getArg(I)->getSourceRange().getEnd()));
+    
+    ArgChanged = ArgChanged || Arg.get() != E->getArg(I);   
+    Args.push_back(Arg.takeAs<Expr>());
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Callee.get() == E->getCallee() &&
+      !ArgChanged)
+    return SemaRef.Owned(E->Retain());
+  
+  // FIXME: Wrong source location information for the '('.
+  SourceLocation FakeLParenLoc 
+    = ((Expr *)Callee.get())->getSourceRange().getBegin();
+  return getDerived().RebuildCallExpr(move(Callee), FakeLParenLoc,
+                                      move_arg(Args),
+                                      FakeCommaLocs.data(),
+                                      E->getRParenLoc());
+}
+  
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { 
+  OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return SemaRef.ExprError();
+  
+  NamedDecl *Member 
+    = cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getMemberDecl()));
+  if (!Member)
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase() &&
+      Member == E->getMemberDecl())
+    return SemaRef.Owned(E->Retain()); 
+
+  // FIXME: Bogus source location for the operator
+  SourceLocation FakeOperatorLoc
+    = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
+
+  return getDerived().RebuildMemberExpr(move(Base), FakeOperatorLoc,
+                                        E->isArrow(),
+                                        E->getMemberLoc(),
+                                        Member);                                        
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformCastExpr(CastExpr *E) { 
+  assert(false && "Cannot transform abstract class");
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+template<typename Derived> 
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { 
+  OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return SemaRef.ExprError();
+  
+  OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
+                                            move(LHS), move(RHS));
+}
+
+template<typename Derived> 
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCompoundAssignOperator(
+                                                  CompoundAssignOperator *E) {
+  return getDerived().TransformBinaryOperator(E);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) { 
+  OwningExprResult Cond = getDerived().TransformExpr(E->getCond());
+  if (Cond.isInvalid())
+    return SemaRef.ExprError();
+  
+  OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return SemaRef.ExprError();
+  
+  OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Cond.get() == E->getCond() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E->Retain());
+  
+  // FIXM: ? and : locations are broken.
+  SourceLocation FakeQuestionLoc = E->getCond()->getLocEnd();
+  SourceLocation FakeColonLoc = E->getFalseExpr()->getLocStart();
+  return getDerived().RebuildConditionalOperator(move(Cond), 
+                                                 FakeQuestionLoc,
+                                                 move(LHS), 
+                                                 FakeColonLoc,
+                                                 move(RHS));
+}
+  
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) { 
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+  
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildImplicitCastExpr(T, E->getCastKind(),
+                                              move(SubExpr), 
+                                              E->isLvalueCast());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformExplicitCastExpr(ExplicitCastExpr *E) { 
+  assert(false && "Cannot transform abstract class");
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) { 
+  QualType T;
+  {
+    // FIXME: Source location isn't quite accurate.
+    SourceLocation TypeStartLoc 
+      = SemaRef.PP.getLocForEndOfToken(E->getLParenLoc());
+    TemporaryBase Rebase(*this, TypeStartLoc, DeclarationName());
+    
+    T = getDerived().TransformType(E->getTypeAsWritten());
+    if (T.isNull())
+      return SemaRef.ExprError();
+  }
+  
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getTypeAsWritten() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildCStyleCaseExpr(E->getLParenLoc(), T,
+                                            E->getRParenLoc(),
+                                            move(SubExpr));
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
+  QualType T;
+  {
+    // FIXME: Source location isn't quite accurate.
+    SourceLocation FakeTypeLoc 
+      = SemaRef.PP.getLocForEndOfToken(E->getLParenLoc());
+    TemporaryBase Rebase(*this, FakeTypeLoc, DeclarationName());
+    
+    T = getDerived().TransformType(E->getType());
+    if (T.isNull())
+      return SemaRef.ExprError();
+  }
+  
+  OwningExprResult Init = getDerived().TransformExpr(E->getInitializer());
+  if (Init.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType() &&
+      Init.get() == E->getInitializer())
+    return SemaRef.Owned(E->Retain()); 
+
+  return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), T,
+                                   /*FIXME:*/E->getInitializer()->getLocEnd(),
+                                                 move(Init));
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) { 
+  OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase())
+    return SemaRef.Owned(E->Retain()); 
+  
+  // FIXME: Bad source location
+  SourceLocation FakeOperatorLoc 
+    = SemaRef.PP.getLocForEndOfToken(E->getBase()->getLocEnd());
+  return getDerived().RebuildExtVectorElementExpr(move(Base), FakeOperatorLoc,
+                                                  E->getAccessorLoc(),
+                                                  E->getAccessor());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) { 
+  bool InitChanged = false;
+  
+  ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
+  for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) {
+    OwningExprResult Init = getDerived().TransformExpr(E->getInit(I));
+    if (Init.isInvalid())
+      return SemaRef.ExprError();
+    
+    InitChanged = InitChanged || Init.get() != E->getInit(I);
+    Inits.push_back(Init.takeAs<Expr>());
+  }
+  
+  if (!getDerived().AlwaysRebuild() && !InitChanged)
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildInitList(E->getLBraceLoc(), move_arg(Inits),
+                                      E->getRBraceLoc());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { 
+  Designation Desig;
+  
+  // Instantiate the initializer value
+  OwningExprResult Init = getDerived().TransformExpr(E->getInit());
+  if (Init.isInvalid())
+    return SemaRef.ExprError();
+  
+  // Instantiate the designators.
+  ASTOwningVector<&ActionBase::DeleteExpr, 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()) {
+      OwningExprResult Index = getDerived().TransformExpr(E->getArrayIndex(*D));
+      if (Index.isInvalid())
+        return SemaRef.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?");
+    OwningExprResult Start 
+      = getDerived().TransformExpr(E->getArrayRangeStart(*D));
+    if (Start.isInvalid())
+      return SemaRef.ExprError();
+    
+    OwningExprResult End = getDerived().TransformExpr(E->getArrayRangeEnd(*D));
+    if (End.isInvalid())
+      return SemaRef.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->Retain());
+  
+  return getDerived().RebuildDesignatedInitExpr(Desig, move_arg(ArrayExprs),
+                                                E->getEqualOrColonLoc(),
+                                                E->usesGNUSyntax(), move(Init));
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformImplicitValueInitExpr(
+                                                    ImplicitValueInitExpr *E) { 
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildImplicitValueInitExpr(T);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) {
+  // FIXME: Do we want the type as written?
+  QualType T;
+  
+  {
+    // FIXME: Source location isn't quite accurate.
+    TemporaryBase Rebase(*this, E->getBuiltinLoc(), DeclarationName());
+    T = getDerived().TransformType(E->getType());
+    if (T.isNull())
+      return SemaRef.ExprError();
+  }
+  
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain());
+  
+  return getDerived().RebuildVAArgExpr(E->getBuiltinLoc(), move(SubExpr),
+                                       T, E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
+  for (unsigned I = 0, N = E->getNumExprs(); I != N; ++I) {
+    OwningExprResult Init = getDerived().TransformExpr(E->getExpr(I));
+    if (Init.isInvalid())
+      return SemaRef.ExprError();
+    
+    ArgumentChanged = ArgumentChanged || Init.get() != E->getExpr(I);
+    Inits.push_back(Init.takeAs<Expr>());
+  }
+  
+  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>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E) { 
+  return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(),
+                                           E->getLabel());
+}
+  
+template<typename Derived> 
+Sema::OwningExprResult TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
+  OwningStmtResult SubStmt 
+    = getDerived().TransformCompoundStmt(E->getSubStmt(), true);
+  if (SubStmt.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      SubStmt.get() == E->getSubStmt())
+    return SemaRef.Owned(E->Retain());
+  
+  return getDerived().RebuildStmtExpr(E->getLParenLoc(), 
+                                      move(SubStmt),
+                                      E->getRParenLoc());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformTypesCompatibleExpr(TypesCompatibleExpr *E) { 
+  QualType T1, T2;
+  {
+    // FIXME: Source location isn't quite accurate.
+    TemporaryBase Rebase(*this, E->getBuiltinLoc(), DeclarationName());
+    
+    T1 = getDerived().TransformType(E->getArgType1());
+    if (T1.isNull())
+      return SemaRef.ExprError();
+    
+    T2 = getDerived().TransformType(E->getArgType2());
+    if (T2.isNull())
+      return SemaRef.ExprError();
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      T1 == E->getArgType1() &&
+      T2 == E->getArgType2())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildTypesCompatibleExpr(E->getBuiltinLoc(),
+                                                 T1, T2, E->getRParenLoc());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) { 
+  OwningExprResult Cond = getDerived().TransformExpr(E->getCond());
+  if (Cond.isInvalid())
+    return SemaRef.ExprError();
+  
+  OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return SemaRef.ExprError();
+  
+  OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Cond.get() == E->getCond() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildChooseExpr(E->getBuiltinLoc(),
+                                        move(Cond), move(LHS), move(RHS),
+                                        E->getRParenLoc());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+  OwningExprResult Callee = getDerived().TransformExpr(E->getCallee());
+  if (Callee.isInvalid())
+    return SemaRef.ExprError();
+  
+  OwningExprResult First = getDerived().TransformExpr(E->getArg(0));
+  if (First.isInvalid())
+    return SemaRef.ExprError();
+
+  OwningExprResult Second(SemaRef);
+  if (E->getNumArgs() == 2) {
+    Second = getDerived().TransformExpr(E->getArg(1));
+    if (Second.isInvalid())
+      return SemaRef.ExprError();
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Callee.get() == E->getCallee() &&
+      First.get() == E->getArg(0) &&
+      (E->getNumArgs() != 2 || Second.get() == E->getArg(1)))    
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
+                                                 E->getOperatorLoc(),
+                                                 move(Callee), 
+                                                 move(First),
+                                                 move(Second));
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) { 
+  return getDerived().TransformCallExpr(E);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
+  QualType ExplicitTy;
+  {
+    // FIXME: Source location isn't quite accurate.
+    SourceLocation TypeStartLoc 
+      = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
+    TemporaryBase Rebase(*this, TypeStartLoc, DeclarationName());
+  
+    ExplicitTy = getDerived().TransformType(E->getTypeAsWritten());
+    if (ExplicitTy.isNull())
+      return SemaRef.ExprError();
+  }
+  
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ExplicitTy == E->getTypeAsWritten() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain()); 
+  
+  // 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,
+                                              ExplicitTy,
+                                              FakeRAngleLoc,
+                                              FakeRAngleLoc,
+                                              move(SubExpr),
+                                              FakeRParenLoc);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) { 
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E) { 
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXReinterpretCastExpr(
+                                                CXXReinterpretCastExpr *E) { 
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E) { 
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
+                                                   CXXFunctionalCastExpr *E) { 
+  QualType ExplicitTy;
+  {
+    TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
+    
+    ExplicitTy = getDerived().TransformType(E->getTypeAsWritten());
+    if (ExplicitTy.isNull())
+      return SemaRef.ExprError();
+  }
+  
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      ExplicitTy == E->getTypeAsWritten() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain()); 
+  
+  // FIXME: The end of the type's source range is wrong
+  return getDerived().RebuildCXXFunctionalCastExpr(
+                                  /*FIXME:*/SourceRange(E->getTypeBeginLoc()),
+                                                   ExplicitTy,
+                                      /*FIXME:*/E->getSubExpr()->getLocStart(),
+                                                   move(SubExpr),
+                                                   E->getRParenLoc());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { 
+  if (E->isTypeOperand()) {
+    TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
+    
+    QualType T = getDerived().TransformType(E->getTypeOperand());
+    if (T.isNull())
+      return SemaRef.ExprError();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        T == E->getTypeOperand())
+      return SemaRef.Owned(E->Retain());
+    
+    return getDerived().RebuildCXXTypeidExpr(E->getLocStart(),
+                                             /*FIXME:*/E->getLocStart(),
+                                             T,
+                                             E->getLocEnd());
+  }
+  
+  // We don't know whether the expression is potentially evaluated until
+  // after we perform semantic analysis, so the expression is potentially
+  // potentially evaluated.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, 
+                                      Action::PotentiallyPotentiallyEvaluated);
+  
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      SubExpr.get() == E->getExprOperand())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildCXXTypeidExpr(E->getLocStart(),
+                                           /*FIXME:*/E->getLocStart(),
+                                           move(SubExpr),
+                                           E->getLocEnd());
+}
+
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
+                                                  CXXNullPtrLiteralExpr *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
+  TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+    
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+    
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType())
+    return SemaRef.Owned(E->Retain());
+ 
+  return getDerived().RebuildCXXThisExpr(E->getLocStart(), T);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) { 
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain()); 
+
+  return getDerived().RebuildCXXThrowExpr(E->getThrowLoc(), move(SubExpr));
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { 
+  ParmVarDecl *Param 
+    = cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getParam()));
+  if (!Param)
+    return SemaRef.ExprError();
+  
+  if (getDerived().AlwaysRebuild() &&
+      Param == E->getParam())
+    return SemaRef.Owned(E->Retain());
+  
+  return getDerived().RebuildCXXDefaultArgExpr(Param);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
+  TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
+
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+    
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildCXXZeroInitValueExpr(E->getTypeBeginLoc(), 
+                                                /*FIXME:*/E->getTypeBeginLoc(),
+                                                  T,
+                                                  E->getRParenLoc());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) {
+  VarDecl *Var 
+    = cast_or_null<VarDecl>(getDerived().TransformDecl(E->getVarDecl()));
+  if (!Var)
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Var == E->getVarDecl())    
+    return SemaRef.Owned(E->Retain());
+  
+  return getDerived().RebuildCXXConditionDeclExpr(E->getStartLoc(), 
+                                                  /*FIXME:*/E->getStartLoc(),
+                                                  Var);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { 
+  // Transform the type that we're allocating
+  TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+  QualType AllocType = getDerived().TransformType(E->getAllocatedType());
+  if (AllocType.isNull())
+    return SemaRef.ExprError();
+  
+  // Transform the size of the array we're allocating (if any).
+  OwningExprResult ArraySize = getDerived().TransformExpr(E->getArraySize());
+  if (ArraySize.isInvalid())
+    return SemaRef.ExprError();
+  
+  // Transform the placement arguments (if any).
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> PlacementArgs(SemaRef);
+  for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
+    OwningExprResult Arg = getDerived().TransformExpr(E->getPlacementArg(I));
+    if (Arg.isInvalid())
+      return SemaRef.ExprError();
+    
+    ArgumentChanged = ArgumentChanged || Arg.get() != E->getPlacementArg(I);
+    PlacementArgs.push_back(Arg.take());
+  }
+  
+  // Instantiate the constructor arguments (if any).
+  ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(SemaRef);
+  for (unsigned I = 0, N = E->getNumConstructorArgs(); I != N; ++I) {
+    OwningExprResult Arg = getDerived().TransformExpr(E->getConstructorArg(I));
+    if (Arg.isInvalid())
+      return SemaRef.ExprError();
+    
+    ArgumentChanged = ArgumentChanged || Arg.get() != E->getConstructorArg(I);
+    ConstructorArgs.push_back(Arg.take());
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      AllocType == E->getAllocatedType() &&
+      ArraySize.get() == E->getArraySize() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildCXXNewExpr(E->getLocStart(),
+                                        E->isGlobalNew(),
+                                        /*FIXME:*/E->getLocStart(),
+                                        move_arg(PlacementArgs),
+                                        /*FIXME:*/E->getLocStart(),
+                                        E->isParenTypeId(),
+                                        AllocType,
+                                        /*FIXME:*/E->getLocStart(),
+                                        /*FIXME:*/SourceRange(),
+                                        move(ArraySize),
+                                        /*FIXME:*/E->getLocStart(),
+                                        move_arg(ConstructorArgs),
+                                        E->getLocEnd());  
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) { 
+  OwningExprResult Operand = getDerived().TransformExpr(E->getArgument());
+  if (Operand.isInvalid())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Operand.get() == E->getArgument())    
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildCXXDeleteExpr(E->getLocStart(),
+                                           E->isGlobalDelete(),
+                                           E->isArrayForm(),
+                                           move(Operand));
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformUnresolvedFunctionNameExpr(
+                                              UnresolvedFunctionNameExpr *E) { 
+  // There is no transformation we can apply to an unresolved function name.
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { 
+  TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
+  
+  QualType T = getDerived().TransformType(E->getQueriedType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getQueriedType())
+    return SemaRef.Owned(E->Retain());
+    
+  // FIXME: Bad location information
+  SourceLocation FakeLParenLoc
+    = SemaRef.PP.getLocForEndOfToken(E->getLocStart());
+  
+  return getDerived().RebuildUnaryTypeTrait(E->getTrait(), 
+                                            E->getLocStart(),
+                                            /*FIXME:*/FakeLParenLoc,
+                                            T,
+                                            E->getLocEnd());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformQualifiedDeclRefExpr(QualifiedDeclRefExpr *E) {
+  NestedNameSpecifier *NNS
+    = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+                                                E->getQualifierRange());
+  if (!NNS)
+    return SemaRef.ExprError();
+  
+  NamedDecl *ND 
+    = dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl()));
+  if (!ND)
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() && 
+      NNS == E->getQualifier() &&
+      ND == E->getDecl())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildQualifiedDeclRefExpr(NNS, 
+                                                  E->getQualifierRange(),
+                                                  ND,
+                                                  E->getLocation(),
+                                                  /*FIXME:*/false);
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(
+                                                    UnresolvedDeclRefExpr *E) { 
+  NestedNameSpecifier *NNS
+  = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+                                              E->getQualifierRange());
+  if (!NNS)
+    return SemaRef.ExprError();
+  
+  // FIXME: Transform the declaration name
+  DeclarationName Name = E->getDeclName();
+  
+  if (!getDerived().AlwaysRebuild() && 
+      NNS == E->getQualifier() &&
+      Name == E->getDeclName())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildUnresolvedDeclRefExpr(NNS, 
+                                                   E->getQualifierRange(),
+                                                   Name,
+                                                   E->getLocation(),
+                                                   /*FIXME:*/false);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) { 
+  TemplateName Template 
+    = getDerived().TransformTemplateName(E->getTemplateName());
+  if (Template.isNull())
+    return SemaRef.ExprError();
+  
+  llvm::SmallVector<TemplateArgument, 4> TransArgs;
+  for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+    TemplateArgument TransArg 
+      = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]);
+    if (TransArg.isNull())
+      return SemaRef.ExprError();
+
+    TransArgs.push_back(TransArg);
+  }
+
+  // FIXME: Would like to avoid rebuilding if nothing changed, but we can't
+  // compare template arguments (yet).
+  
+  // FIXME: It's possible that we'll find out now that the template name 
+  // actually refers to a type, in which case the caller is actually dealing
+  // with a functional cast. Give a reasonable error message!
+  return getDerived().RebuildTemplateIdExpr(Template, E->getTemplateNameLoc(),
+                                            E->getLAngleLoc(),
+                                            TransArgs.data(),
+                                            TransArgs.size(),
+                                            E->getRAngleLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { 
+  TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
+
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  CXXConstructorDecl *Constructor
+    = cast_or_null<CXXConstructorDecl>(
+                              getDerived().TransformDecl(E->getConstructor()));
+  if (!Constructor)
+    return SemaRef.ExprError();
+  
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+  for (CXXConstructExpr::arg_iterator Arg = E->arg_begin(), 
+       ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg) {
+    OwningExprResult TransArg = getDerived().TransformExpr(*Arg);
+    if (TransArg.isInvalid())
+      return SemaRef.ExprError();
+    
+    ArgumentChanged = ArgumentChanged || TransArg.get() != *Arg;
+    Args.push_back(TransArg.takeAs<Expr>());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType() &&
+      Constructor == E->getConstructor() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain());
+  
+  return getDerived().RebuildCXXConstructExpr(T, Constructor, E->isElidable(),
+                                              move_arg(Args));
+}
+  
+/// \brief Transform a C++ temporary-binding expression.
+///
+/// The transformation of a temporary-binding expression always attempts to 
+/// bind a new temporary variable to its subexpression, even if the 
+/// subexpression itself did not change, because the temporary variable itself
+/// must be unique.
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  return SemaRef.MaybeBindToTemporary(SubExpr.takeAs<Expr>());
+}
+  
+/// \brief Transform a C++ expression that contains temporaries that should 
+/// be destroyed after the expression is evaluated.
+///
+/// The transformation of a full expression always attempts to build a new 
+/// CXXExprWithTemporaries expression, even if the 
+/// subexpression itself did not change, because it will need to capture the
+/// the new temporary variables introduced in the subexpression.
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXExprWithTemporaries(
+                                                CXXExprWithTemporaries *E) { 
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  return SemaRef.Owned(
+           SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>(),
+                                               E->shouldDestroyTemporaries()));
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
+                                                  CXXTemporaryObjectExpr *E) { 
+  TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+  
+  CXXConstructorDecl *Constructor
+    = cast_or_null<CXXConstructorDecl>(
+                            getDerived().TransformDecl(E->getConstructor()));
+  if (!Constructor)
+    return SemaRef.ExprError();
+  
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+  Args.reserve(E->getNumArgs());
+  for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(), 
+                                         ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg) {
+    OwningExprResult TransArg = getDerived().TransformExpr(*Arg);
+    if (TransArg.isInvalid())
+      return SemaRef.ExprError();
+    
+    ArgumentChanged = ArgumentChanged || TransArg.get() != *Arg;
+    Args.push_back((Expr *)TransArg.release());
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType() &&
+      Constructor == E->getConstructor() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain());
+  
+  // FIXME: Bogus location information
+  SourceLocation CommaLoc;
+  if (Args.size() > 1) {
+    Expr *First = (Expr *)Args[0];
+    CommaLoc 
+      = SemaRef.PP.getLocForEndOfToken(First->getSourceRange().getEnd());
+  }
+  return getDerived().RebuildCXXTemporaryObjectExpr(E->getTypeBeginLoc(),
+                                                    T,
+                                                /*FIXME:*/E->getTypeBeginLoc(),
+                                                    move_arg(Args),
+                                                    &CommaLoc,
+                                                    E->getLocEnd());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
+                                            CXXUnresolvedConstructExpr *E) { 
+  TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
+  QualType T = getDerived().TransformType(E->getTypeAsWritten());
+  if (T.isNull())
+    return SemaRef.ExprError();
+  
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+  llvm::SmallVector<SourceLocation, 8> FakeCommaLocs;
+  for (CXXUnresolvedConstructExpr::arg_iterator Arg = E->arg_begin(),
+                                             ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg) {
+    OwningExprResult TransArg = getDerived().TransformExpr(*Arg);
+    if (TransArg.isInvalid())
+      return SemaRef.ExprError();
+    
+    ArgumentChanged = ArgumentChanged || TransArg.get() != *Arg;
+    FakeCommaLocs.push_back(
+                        SemaRef.PP.getLocForEndOfToken((*Arg)->getLocEnd()));
+    Args.push_back(TransArg.takeAs<Expr>());
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getTypeAsWritten() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain()); 
+  
+  // FIXME: we're faking the locations of the commas
+  return getDerived().RebuildCXXUnresolvedConstructExpr(E->getTypeBeginLoc(),
+                                                        T,
+                                                        E->getLParenLoc(),
+                                                        move_arg(Args),
+                                                        FakeCommaLocs.data(),
+                                                        E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
+                                                  CXXUnresolvedMemberExpr *E) { 
+  // Transform the base of the expression.
+  OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return SemaRef.ExprError();
+  
+  // FIXME: Transform the declaration name
+  DeclarationName Name = E->getMember();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase() &&
+      Name == E->getMember())
+    return SemaRef.Owned(E->Retain()); 
+      
+  return getDerived().RebuildCXXUnresolvedMemberExpr(move(Base),
+                                                     E->isArrow(),
+                                                     E->getOperatorLoc(),
+                                                     E->getMember(),
+                                                     E->getMemberLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) { 
+  // FIXME: poor source location
+  TemporaryBase Rebase(*this, E->getAtLoc(), DeclarationName());
+  QualType EncodedType = getDerived().TransformType(E->getEncodedType());
+  if (EncodedType.isNull())
+    return SemaRef.ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      EncodedType == E->getEncodedType())
+    return SemaRef.Owned(E->Retain()); 
+
+  return getDerived().RebuildObjCEncodeExpr(E->getAtLoc(),
+                                            EncodedType,
+                                            E->getRParenLoc());
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { 
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E) { 
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) { 
+  ObjCProtocolDecl *Protocol 
+    = cast_or_null<ObjCProtocolDecl>(
+                                getDerived().TransformDecl(E->getProtocol()));
+  if (!Protocol)
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Protocol == E->getProtocol())
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildObjCProtocolExpr(Protocol,
+                                              E->getAtLoc(),
+                                              /*FIXME:*/E->getAtLoc(),
+                                              /*FIXME:*/E->getAtLoc(),
+                                              E->getRParenLoc());
+                                              
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) { 
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformObjCKVCRefExpr(ObjCKVCRefExpr *E) { 
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E) { 
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) { 
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { 
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> SubExprs(SemaRef);
+  for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) {
+    OwningExprResult SubExpr = getDerived().TransformExpr(E->getExpr(I));
+    if (SubExpr.isInvalid())
+      return SemaRef.ExprError();
+    
+    ArgumentChanged = ArgumentChanged || SubExpr.get() != E->getExpr(I);
+    SubExprs.push_back(SubExpr.takeAs<Expr>());
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain()); 
+  
+  return getDerived().RebuildShuffleVectorExpr(E->getBuiltinLoc(),
+                                               move_arg(SubExprs),
+                                               E->getRParenLoc());
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { 
+  // FIXME: Implement this!
+  assert(false && "Cannot transform block expressions yet");
+  return SemaRef.Owned(E->Retain()); 
+}
+
+template<typename Derived> 
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { 
+  // FIXME: Implement this!
+  assert(false && "Cannot transform block-related expressions yet");
+  return SemaRef.Owned(E->Retain()); 
+}
+  
+//===----------------------------------------------------------------------===//
+// Type reconstruction
+//===----------------------------------------------------------------------===//
+
+template<typename Derived> 
+QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
+  return SemaRef.BuildPointerType(PointeeType, 0, 
+                                  getDerived().getBaseLocation(),
+                                  getDerived().getBaseEntity());
+}
+
+template<typename Derived> 
+QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
+  return SemaRef.BuildBlockPointerType(PointeeType, 0, 
+                                       getDerived().getBaseLocation(),
+                                       getDerived().getBaseEntity());
+}
+
+template<typename Derived> 
+QualType 
+TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
+  return SemaRef.BuildReferenceType(ReferentType, true, 0, 
+                                    getDerived().getBaseLocation(),
+                                    getDerived().getBaseEntity());
 }
 
 template<typename Derived> 
@@ -1352,7 +3593,7 @@
 QualType 
 TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType, 
                                           ArrayType::ArraySizeModifier SizeMod,
-                                                 Sema::ExprArg SizeExpr,
+                                                 ExprArg SizeExpr,
                                                  unsigned IndexTypeQuals,
                                                  SourceRange BracketsRange) {
   return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 
@@ -1364,7 +3605,7 @@
 QualType 
 TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType, 
                                           ArrayType::ArraySizeModifier SizeMod,
-                                                       Sema::ExprArg SizeExpr,
+                                                       ExprArg SizeExpr,
                                                        unsigned IndexTypeQuals,
                                                    SourceRange BracketsRange) {
   return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 
@@ -1395,7 +3636,7 @@
 template<typename Derived>
 QualType 
 TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType, 
-                                                         Sema::ExprArg SizeExpr,
+                                                           ExprArg SizeExpr,
                                                   SourceLocation AttributeLoc) {
   return SemaRef.BuildExtVectorType(ElementType, move(SizeExpr), AttributeLoc);
 }
@@ -1413,7 +3654,7 @@
 }
   
 template<typename Derived>
-QualType TreeTransform<Derived>::RebuildTypeOfExprType(Sema::ExprArg E) {
+QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {
   return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
 }
 
@@ -1423,7 +3664,7 @@
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::RebuildDecltypeType(Sema::ExprArg E) {
+QualType TreeTransform<Derived>::RebuildDecltypeType(ExprArg E) {
   return SemaRef.BuildDecltypeType(E.takeAs<Expr>());
 }
 
@@ -1521,6 +3762,87 @@
   
   return Template.getAsVal<TemplateName>();  
 }
+ 
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
+                                                   SourceLocation OpLoc,
+                                                   ExprArg Callee,
+                                                   ExprArg First,
+                                                   ExprArg Second) {
+  Expr *FirstExpr = (Expr *)First.get();
+  Expr *SecondExpr = (Expr *)Second.get();
+  bool isPostIncDec = SecondExpr && (Op == OO_PlusPlus || Op == OO_MinusMinus);
+    
+  // Determine whether this should be a builtin operation.
+  if (SecondExpr == 0 || isPostIncDec) {
+    if (!FirstExpr->getType()->isOverloadableType()) {
+      // The argument is not of overloadable type, so try to create a
+      // built-in unary operation.
+      UnaryOperator::Opcode Opc 
+        = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+      
+      return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, move(First));
+    }
+  } else {
+    if (!FirstExpr->getType()->isOverloadableType() && 
+        !SecondExpr->getType()->isOverloadableType()) {
+      // Neither of the arguments is an overloadable type, so try to
+      // create a built-in binary operation.
+      BinaryOperator::Opcode Opc = BinaryOperator::getOverloadedOpcode(Op);
+      OwningExprResult Result 
+        = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, FirstExpr, SecondExpr);
+      if (Result.isInvalid())
+        return SemaRef.ExprError();
+      
+      First.release();
+      Second.release();
+      return move(Result);
+    }
+  }
+  
+  // Compute the transformed set of functions (and function templates) to be 
+  // used during overload resolution.
+  Sema::FunctionSet Functions;
+  
+  DeclRefExpr *DRE = cast<DeclRefExpr>((Expr *)Callee.get());
+  OverloadedFunctionDecl *Overloads 
+    = cast<OverloadedFunctionDecl>(DRE->getDecl());
+  
+  // FIXME: Do we have to check
+  // IsAcceptableNonMemberOperatorCandidate for each of these?
+  for (OverloadedFunctionDecl::function_iterator 
+       F = Overloads->function_begin(),
+       FEnd = Overloads->function_end();
+       F != FEnd; ++F)
+    Functions.insert(*F);
+  
+  // Add any functions found via argument-dependent lookup.
+  Expr *Args[2] = { FirstExpr, SecondExpr };
+  unsigned NumArgs = 1 + (SecondExpr != 0);
+  DeclarationName OpName 
+    = SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
+  SemaRef.ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
+  
+  // Create the overloaded operator invocation for unary operators.
+  if (NumArgs == 1 || isPostIncDec) {
+    UnaryOperator::Opcode Opc 
+      = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+    return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(First));
+  }
+  
+  // Create the overloaded operator invocation for binary operators.
+  BinaryOperator::Opcode Opc = 
+    BinaryOperator::getOverloadedOpcode(Op);
+  OwningExprResult Result 
+    = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, Args[0], Args[1]);
+  if (Result.isInvalid())
+    return SemaRef.ExprError();
+  
+  First.release();
+  Second.release();
+  return move(Result);  
+}
   
 } // end namespace clang
 





More information about the cfe-commits mailing list