diff options
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 146 |
1 files changed, 100 insertions, 46 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 4bd7ad4e83..4c3f100d74 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -584,6 +584,7 @@ namespace { OwningExprResult VisitIntegerLiteral(IntegerLiteral *E); OwningExprResult VisitDeclRefExpr(DeclRefExpr *E); OwningExprResult VisitParenExpr(ParenExpr *E); + OwningExprResult VisitUnaryOperator(UnaryOperator *E); OwningExprResult VisitBinaryOperator(BinaryOperator *E); OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); @@ -634,6 +635,17 @@ TemplateExprInstantiator::VisitParenExpr(ParenExpr *E) { } 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::VisitBinaryOperator(BinaryOperator *E) { Sema::OwningExprResult LHS = Visit(E->getLHS()); if (LHS.isInvalid()) @@ -658,74 +670,116 @@ TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) { Sema::OwningExprResult TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { - // FIXME: Only handles binary operators at the moment. - - Sema::OwningExprResult LHS = Visit(E->getArg(0)); - if (LHS.isInvalid()) + Sema::OwningExprResult First = Visit(E->getArg(0)); + if (First.isInvalid()) return SemaRef.ExprError(); - Sema::OwningExprResult RHS = Visit(E->getArg(1)); - if (RHS.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(); - Expr *lhs = (Expr *)LHS.get(), *rhs = (Expr *)RHS.get(); - Expr *Args[2] = { lhs, rhs }; + 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. - LHS.release(); - RHS.release(); + First.release(); + Second.release(); return SemaRef.Owned(new (SemaRef.Context) CXXOperatorCallExpr( SemaRef.Context, E->getOperator(), E->getCallee(), - Args, 2, E->getType(), + Args, E->getNumArgs(), + E->getType(), E->getOperatorLoc())); } - BinaryOperator::Opcode Opc = - BinaryOperator::getOverloadedOpcode(E->getOperator()); - Sema::OwningExprResult Result(SemaRef); - if (!lhs->getType()->isOverloadableType() && - !rhs->getType()->isOverloadableType()) { - // Neither LHS nor RHS is an overloadable type, so try create a - // built-in binary operation. - Result = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), Opc, - lhs, rhs); + 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 { - // Compute the set of functions that were found at template - // definition time. - Sema::FunctionSet Functions; - DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee()); - OverloadedFunctionDecl *Overloads - = cast<OverloadedFunctionDecl>(DRE->getDecl()); - - // FIXME: Do we have to check - // IsAcceptableNonMemberOperatorCandidate for each of these? - for (OverloadedFunctionDecl::function_iterator - F = Overloads->function_begin(), - FEnd = Overloads->function_end(); - F != FEnd; ++F) - Functions.insert(*F); - - // Add any functions found via argument-dependent lookup. - DeclarationName OpName - = SemaRef.Context.DeclarationNames.getCXXOperatorName(E->getOperator()); - SemaRef.ArgumentDependentLookup(OpName, Args, 2, Functions); - - // Create the overloaded operator. - Result = SemaRef.CreateOverloadedBinOp(E->getOperatorLoc(), Opc, - Functions, lhs, rhs); + assert(E->getNumArgs() == 2 && "Expected binary operation"); + + Sema::OwningExprResult Result(SemaRef); + if (!Args[0]->getType()->isOverloadableType() && + !Args[1]->getType()->isOverloadableType()) { + // Neither of the arguments is an overloadable type, so try to + // create a built-in binary operation. + BinaryOperator::Opcode Opc = + BinaryOperator::getOverloadedOpcode(E->getOperator()); + Result = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), Opc, + Args[0], Args[1]); + if (Result.isInvalid()) + return SemaRef.ExprError(); + + First.release(); + Second.release(); + return move(Result); + } + + // Fall through to perform overload resolution. } + // Compute the set of functions that were found at template + // definition time. + Sema::FunctionSet Functions; + DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee()); + OverloadedFunctionDecl *Overloads + = cast<OverloadedFunctionDecl>(DRE->getDecl()); + + // FIXME: Do we have to check + // IsAcceptableNonMemberOperatorCandidate for each of these? + for (OverloadedFunctionDecl::function_iterator + F = Overloads->function_begin(), + FEnd = Overloads->function_end(); + F != FEnd; ++F) + Functions.insert(*F); + + // Add any functions found via argument-dependent lookup. + DeclarationName OpName + = SemaRef.Context.DeclarationNames.getCXXOperatorName(E->getOperator()); + SemaRef.ArgumentDependentLookup(OpName, Args, E->getNumArgs(), Functions); + + // Create the overloaded operator invocation. + if (E->getNumArgs() == 1 || isPostIncDec) { + UnaryOperator::Opcode Opc + = UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec); + return SemaRef.CreateOverloadedUnaryOp(E->getOperatorLoc(), Opc, + Functions, move(First)); + } + + // FIXME: This would be far less ugly if CreateOverloadedBinOp took + // in ExprArg arguments! + BinaryOperator::Opcode Opc = + BinaryOperator::getOverloadedOpcode(E->getOperator()); + OwningExprResult Result + = SemaRef.CreateOverloadedBinOp(E->getOperatorLoc(), Opc, + Functions, Args[0], Args[1]); + if (Result.isInvalid()) return SemaRef.ExprError(); - LHS.release(); - RHS.release(); + First.release(); + Second.release(); return move(Result); } |