diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-12-13 20:44:55 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-12-13 20:44:55 +0000 |
commit | 668d6d9dc100b3ef28a9b8e6fe987c2f5b6edcc9 (patch) | |
tree | bb085c053e4b5345bd5e289964d77dc4c2591444 | |
parent | dd9375513db874caadaeff62ef10becbe32bd7fb (diff) |
Fix template instantiation for non-dependent calls to overloaded call
operators. Fixes PR5266.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91252 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/TreeTransform.h | 62 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-expr-1.cpp | 18 |
2 files changed, 80 insertions, 0 deletions
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index f8e8f947be..dc848a53ab 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -4131,6 +4131,68 @@ TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) { template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { + switch (E->getOperator()) { + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + llvm_unreachable("new and delete operators cannot use CXXOperatorCallExpr"); + return SemaRef.ExprError(); + + case OO_Call: { + // This is a call to an object's operator(). + assert(E->getNumArgs() >= 1 && "Object call is missing arguments"); + + // Transform the object itself. + OwningExprResult Object = getDerived().TransformExpr(E->getArg(0)); + if (Object.isInvalid()) + return SemaRef.ExprError(); + + // FIXME: Poor location information + SourceLocation FakeLParenLoc + = SemaRef.PP.getLocForEndOfToken( + static_cast<Expr *>(Object.get())->getLocEnd()); + + // Transform the call arguments. + ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef); + llvm::SmallVector<SourceLocation, 4> FakeCommaLocs; + for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I) { + OwningExprResult Arg = getDerived().TransformExpr(E->getArg(I)); + if (Arg.isInvalid()) + return SemaRef.ExprError(); + + // FIXME: Poor source location information. + SourceLocation FakeCommaLoc + = SemaRef.PP.getLocForEndOfToken( + static_cast<Expr *>(Arg.get())->getLocEnd()); + FakeCommaLocs.push_back(FakeCommaLoc); + Args.push_back(Arg.release()); + } + + return getDerived().RebuildCallExpr(move(Object), FakeLParenLoc, + move_arg(Args), + FakeCommaLocs.data(), + E->getLocEnd()); + } + +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + case OO_##Name: +#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) +#include "clang/Basic/OperatorKinds.def" + case OO_Subscript: + // Handled below. + break; + + case OO_Conditional: + llvm_unreachable("conditional operator is not actually overloadable"); + return SemaRef.ExprError(); + + case OO_None: + case NUM_OVERLOADED_OPERATORS: + llvm_unreachable("not an overloaded operator?"); + return SemaRef.ExprError(); + } + OwningExprResult Callee = getDerived().TransformExpr(E->getCallee()); if (Callee.isInvalid()) return SemaRef.ExprError(); diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp index fb88213c40..1cd55d9ad2 100644 --- a/test/SemaTemplate/instantiate-expr-1.cpp +++ b/test/SemaTemplate/instantiate-expr-1.cpp @@ -94,3 +94,21 @@ struct Addable { void test_add(Addable &a) { add(a); } + +struct CallOperator { + int &operator()(int); + double &operator()(double); +}; + +template<typename Result, typename F, typename Arg1> +Result test_call_operator(F f, Arg1 arg1) { + // PR5266: non-dependent invocations of a function call operator. + CallOperator call_op; + int &ir = call_op(17); + return f(arg1); +} + +void test_call_operator(CallOperator call_op, int i, double d) { + int &ir = test_call_operator<int&>(call_op, i); + double &dr = test_call_operator<double&>(call_op, d); +} |