From: Douglas Gregor Date: Tue, 11 Aug 2009 05:31:07 +0000 (+0000) Subject: Refactor the template-instantiation logic for expressions into a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b98b1991c7ad1eaedb863bdbdd784ec164277675;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78645 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 924ad3970f..e278d1763a 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -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 @@ STMT(CXXTryStmt , Stmt) LAST_STMT(CXXTryStmt) // Expressions. -EXPR(Expr , Stmt) +ABSTRACT_EXPR(Expr , Stmt) FIRST_EXPR(Expr) EXPR(PredefinedExpr , Expr) EXPR(DeclRefExpr , Expr) @@ -151,8 +155,9 @@ EXPR(BlockDeclRefExpr , Expr) LAST_EXPR(BlockDeclRefExpr) -#undef STMT +#undef ABSTRACT_EXPR #undef EXPR +#undef STMT #undef FIRST_STMT #undef LAST_STMT #undef FIRST_EXPR diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 54a6dd549d..25007d2fde 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -26,7 +26,6 @@ add_clang_library(clangSema SemaTemplateDeduction.cpp SemaTemplateInstantiate.cpp SemaTemplateInstantiateDecl.cpp - SemaTemplateInstantiateExpr.cpp SemaTemplateInstantiateStmt.cpp SemaType.cpp ) diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 8f877a8b56..4d164ea12e 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -316,24 +316,30 @@ namespace { /// \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(D)) { @@ -351,6 +357,93 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { return SemaRef.InstantiateCurrentDeclRef(cast_or_null(D)); } +Sema::OwningExprResult +TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { + // FIXME: Clean this up a bit + NamedDecl *D = E->getDecl(); + if (NonTypeTemplateParmDecl *NTTP = dyn_cast(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(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(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(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 @@ void Sema::InstantiateClassTemplateSpecializationMembers( 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, diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp deleted file mode 100644 index 7a09210fe0..0000000000 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ /dev/null @@ -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 { - 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 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(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(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(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 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()); - } - - 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(), - 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(E->getCallee()); - OverloadedFunctionDecl *Overloads - = cast(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(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(), - LHS.takeAs(), - RHS.takeAs(), - 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()); - } - - // 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(*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(), - 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()); - } - - 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()); - } - - 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(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()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXConstructExpr(CXXConstructExpr *E) { - assert(!cast(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()); - } - - return SemaRef.Owned(SemaRef.BuildCXXConstructExpr(SemaRef.Context, T, - E->getConstructor(), - E->isElidable(), - Args.takeAs(), - 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(); - 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(), - 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 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()); - } - - // 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); -} diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index c935f8118a..eb61cc5f08 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -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 namespace clang { @@ -80,6 +85,12 @@ protected: 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 @@ public: /// 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 @@ public: /// \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 @@ public: 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 @@ public: /// 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 @@ public: /// 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 @@ public: /// 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 @@ public: /// /// 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 @@ public: /// /// 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 @@ public: /// 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(); + 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(*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 -Sema::OwningExprResult TreeTransform::TransformExpr(Expr *E) { - Sema::OwningStmtResult Result = getDerived().TransformStmt(E); - if (Result.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.Owned(cast_or_null(Result.takeAs())); +Sema::OwningExprResult TreeTransform::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(E)); +#include "clang/AST/StmtNodes.def" + } + + return SemaRef.Owned(E->Retain()); } template @@ -1230,34 +2075,1430 @@ QualType TreeTransform::TransformObjCObjectPointerType( } //===----------------------------------------------------------------------===// -// Type reconstruction +// Expression transformation //===----------------------------------------------------------------------===// - template -QualType TreeTransform::RebuildPointerType(QualType PointeeType) { - return SemaRef.BuildPointerType(PointeeType, 0, - getDerived().getBaseLocation(), - getDerived().getBaseEntity()); +Sema::OwningExprResult +TreeTransform::TransformPredefinedExpr(PredefinedExpr *E) { + return SemaRef.Owned(E->Retain()); } - + template -QualType TreeTransform::RebuildBlockPointerType(QualType PointeeType) { - return SemaRef.BuildBlockPointerType(PointeeType, 0, - getDerived().getBaseLocation(), - getDerived().getBaseEntity()); +Sema::OwningExprResult +TreeTransform::TransformDeclRefExpr(DeclRefExpr *E) { + NamedDecl *ND + = dyn_cast_or_null(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 -QualType -TreeTransform::RebuildLValueReferenceType(QualType ReferentType) { - return SemaRef.BuildReferenceType(ReferentType, true, 0, - getDerived().getBaseLocation(), - getDerived().getBaseEntity()); + +template +Sema::OwningExprResult +TreeTransform::TransformIntegerLiteral(IntegerLiteral *E) { + return SemaRef.Owned(E->Retain()); } - -template -QualType -TreeTransform::RebuildRValueReferenceType(QualType ReferentType) { + +template +Sema::OwningExprResult +TreeTransform::TransformFloatingLiteral(FloatingLiteral *E) { + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformImaginaryLiteral(ImaginaryLiteral *E) { + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformStringLiteral(StringLiteral *E) { + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformCharacterLiteral(CharacterLiteral *E) { + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 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()); + } + + 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 +Sema::OwningExprResult +TreeTransform::TransformMemberExpr(MemberExpr *E) { + OwningExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return SemaRef.ExprError(); + + NamedDecl *Member + = cast_or_null(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 +Sema::OwningExprResult +TreeTransform::TransformCastExpr(CastExpr *E) { + assert(false && "Cannot transform abstract class"); + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformCompoundAssignOperator( + CompoundAssignOperator *E) { + return getDerived().TransformBinaryOperator(E); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformExplicitCastExpr(ExplicitCastExpr *E) { + assert(false && "Cannot transform abstract class"); + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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()); + } + + if (!getDerived().AlwaysRebuild() && !InitChanged) + return SemaRef.Owned(E->Retain()); + + return getDerived().RebuildInitList(E->getLBraceLoc(), move_arg(Inits), + E->getRBraceLoc()); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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()); + } + + 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 +Sema::OwningExprResult +TreeTransform::TransformAddrLabelExpr(AddrLabelExpr *E) { + return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(), + E->getLabel()); +} + +template +Sema::OwningExprResult TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformGNUNullExpr(GNUNullExpr *E) { + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) { + return getDerived().TransformCallExpr(E); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) { + return getDerived().TransformCXXNamedCastExpr(E); +} + +template +Sema::OwningExprResult +TreeTransform::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E) { + return getDerived().TransformCXXNamedCastExpr(E); +} + +template +Sema::OwningExprResult +TreeTransform::TransformCXXReinterpretCastExpr( + CXXReinterpretCastExpr *E) { + return getDerived().TransformCXXNamedCastExpr(E); +} + +template +Sema::OwningExprResult +TreeTransform::TransformCXXConstCastExpr(CXXConstCastExpr *E) { + return getDerived().TransformCXXNamedCastExpr(E); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformCXXNullPtrLiteralExpr( + CXXNullPtrLiteralExpr *E) { + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + ParmVarDecl *Param + = cast_or_null(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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) { + VarDecl *Var + = cast_or_null(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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformUnresolvedFunctionNameExpr( + UnresolvedFunctionNameExpr *E) { + // There is no transformation we can apply to an unresolved function name. + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformQualifiedDeclRefExpr(QualifiedDeclRefExpr *E) { + NestedNameSpecifier *NNS + = getDerived().TransformNestedNameSpecifier(E->getQualifier(), + E->getQualifierRange()); + if (!NNS) + return SemaRef.ExprError(); + + NamedDecl *ND + = dyn_cast_or_null(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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) { + TemplateName Template + = getDerived().TransformTemplateName(E->getTemplateName()); + if (Template.isNull()) + return SemaRef.ExprError(); + + llvm::SmallVector 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 +Sema::OwningExprResult +TreeTransform::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( + 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()); + } + + 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 +Sema::OwningExprResult +TreeTransform::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + if (SubExpr.isInvalid()) + return SemaRef.ExprError(); + + return SemaRef.MaybeBindToTemporary(SubExpr.takeAs()); +} + +/// \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 +Sema::OwningExprResult +TreeTransform::TransformCXXExprWithTemporaries( + CXXExprWithTemporaries *E) { + OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + if (SubExpr.isInvalid()) + return SemaRef.ExprError(); + + return SemaRef.Owned( + SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs(), + E->shouldDestroyTemporaries())); +} + +template +Sema::OwningExprResult +TreeTransform::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( + 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 +Sema::OwningExprResult +TreeTransform::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 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()); + } + + 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 +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformObjCStringLiteral(ObjCStringLiteral *E) { + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::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 +Sema::OwningExprResult +TreeTransform::TransformObjCMessageExpr(ObjCMessageExpr *E) { + // FIXME: Implement this! + assert(false && "Cannot transform Objective-C expressions yet"); + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformObjCSelectorExpr(ObjCSelectorExpr *E) { + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformObjCProtocolExpr(ObjCProtocolExpr *E) { + ObjCProtocolDecl *Protocol + = cast_or_null( + 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 +Sema::OwningExprResult +TreeTransform::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) { + // FIXME: Implement this! + assert(false && "Cannot transform Objective-C expressions yet"); + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { + // FIXME: Implement this! + assert(false && "Cannot transform Objective-C expressions yet"); + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformObjCKVCRefExpr(ObjCKVCRefExpr *E) { + // FIXME: Implement this! + assert(false && "Cannot transform Objective-C expressions yet"); + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformObjCSuperExpr(ObjCSuperExpr *E) { + // FIXME: Implement this! + assert(false && "Cannot transform Objective-C expressions yet"); + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformObjCIsaExpr(ObjCIsaExpr *E) { + // FIXME: Implement this! + assert(false && "Cannot transform Objective-C expressions yet"); + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::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()); + } + + if (!getDerived().AlwaysRebuild() && + !ArgumentChanged) + return SemaRef.Owned(E->Retain()); + + return getDerived().RebuildShuffleVectorExpr(E->getBuiltinLoc(), + move_arg(SubExprs), + E->getRParenLoc()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformBlockExpr(BlockExpr *E) { + // FIXME: Implement this! + assert(false && "Cannot transform block expressions yet"); + return SemaRef.Owned(E->Retain()); +} + +template +Sema::OwningExprResult +TreeTransform::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { + // FIXME: Implement this! + assert(false && "Cannot transform block-related expressions yet"); + return SemaRef.Owned(E->Retain()); +} + +//===----------------------------------------------------------------------===// +// Type reconstruction +//===----------------------------------------------------------------------===// + +template +QualType TreeTransform::RebuildPointerType(QualType PointeeType) { + return SemaRef.BuildPointerType(PointeeType, 0, + getDerived().getBaseLocation(), + getDerived().getBaseEntity()); +} + +template +QualType TreeTransform::RebuildBlockPointerType(QualType PointeeType) { + return SemaRef.BuildBlockPointerType(PointeeType, 0, + getDerived().getBaseLocation(), + getDerived().getBaseEntity()); +} + +template +QualType +TreeTransform::RebuildLValueReferenceType(QualType ReferentType) { + return SemaRef.BuildReferenceType(ReferentType, true, 0, + getDerived().getBaseLocation(), + getDerived().getBaseEntity()); +} + +template +QualType +TreeTransform::RebuildRValueReferenceType(QualType ReferentType) { return SemaRef.BuildReferenceType(ReferentType, false, 0, getDerived().getBaseLocation(), getDerived().getBaseEntity()); @@ -1352,7 +3593,7 @@ template QualType TreeTransform::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 @@ template QualType TreeTransform::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 @@ QualType TreeTransform::RebuildExtVectorType(QualType ElementType, template QualType TreeTransform::RebuildDependentSizedExtVectorType(QualType ElementType, - Sema::ExprArg SizeExpr, + ExprArg SizeExpr, SourceLocation AttributeLoc) { return SemaRef.BuildExtVectorType(ElementType, move(SizeExpr), AttributeLoc); } @@ -1413,7 +3654,7 @@ QualType TreeTransform::RebuildFunctionProtoType(QualType T, } template -QualType TreeTransform::RebuildTypeOfExprType(Sema::ExprArg E) { +QualType TreeTransform::RebuildTypeOfExprType(ExprArg E) { return SemaRef.BuildTypeofExprType(E.takeAs()); } @@ -1423,7 +3664,7 @@ QualType TreeTransform::RebuildTypeOfType(QualType Underlying) { } template -QualType TreeTransform::RebuildDecltypeType(Sema::ExprArg E) { +QualType TreeTransform::RebuildDecltypeType(ExprArg E) { return SemaRef.BuildDecltypeType(E.takeAs()); } @@ -1521,6 +3762,87 @@ TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, return Template.getAsVal(); } + +template +Sema::OwningExprResult +TreeTransform::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((Expr *)Callee.get()); + OverloadedFunctionDecl *Overloads + = cast(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