diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-13 23:49:33 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-13 23:49:33 +0000 |
commit | bc736fceca6f0bca31d16003a7587857190408fb (patch) | |
tree | 795b52807b846a35f25bf0ea3bc6e0edd1671f32 /lib/Sema/SemaTemplateInstantiate.cpp | |
parent | 4db938ceb72dbaa5f7b50f6420a72629acbf29eb (diff) |
Implement template instantiation for the prefix unary operators. As
always, refactored the existing logic to tease apart the parser action
and the semantic analysis shared by the parser and template
instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66987 91177308-0d34-0410-b5e6-96231b3b80d8
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); } |