diff options
-rw-r--r-- | lib/AST/Expr.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 20 | ||||
-rw-r--r-- | test/SemaTemplate/member-template-access-expr.cpp | 27 |
4 files changed, 56 insertions, 4 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 47df95dc71..ad9c9cbe10 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1126,6 +1126,18 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { return LV_Valid; } + case TemplateIdRefExprClass: { + const TemplateIdRefExpr *TID = cast<TemplateIdRefExpr>(this); + TemplateName Template = TID->getTemplateName(); + NamedDecl *ND = Template.getAsTemplateDecl(); + if (!ND) + ND = Template.getAsOverloadedFunctionDecl(); + if (ND && DeclCanBeLvalue(ND, Ctx)) + return LV_Valid; + + break; + } + default: break; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 6f26ea1eee..3aac415c04 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2337,6 +2337,7 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl))) Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + // FIXME: Do we have to know if there are explicit template arguments? if (Method && !Method->isStatic()) { Ctx = Method->getParent(); if (isa<CXXMethodDecl>(D) && !FunTmpl) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7ed79f3073..fbb50aea87 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -4287,10 +4287,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) { Ovl = dyn_cast<OverloadedFunctionDecl>(DR->getDecl()); FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl()); + HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList(); + ExplicitTemplateArgs = DR->getTemplateArgs(); + NumExplicitTemplateArgs = DR->getNumTemplateArgs(); } else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) { Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl()); FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl()); - // FIXME: Explicit template arguments + HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList(); + ExplicitTemplateArgs = ME->getTemplateArgs(); + NumExplicitTemplateArgs = ME->getNumTemplateArgs(); } else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) { TemplateName Name = TIRE->getTemplateName(); Ovl = Name.getAsOverloadedFunctionDecl(); @@ -4367,6 +4372,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // when converting to member pointer. if (Method->isStatic() == IsMember) continue; + + // If we have explicit template arguments, skip non-templates. + if (HasExplicitTemplateArgs) + continue; } else if (IsMember) continue; @@ -4967,10 +4976,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, for (OverloadIterator Func(MemExpr->getMemberDecl()), FuncEnd; Func != FuncEnd; ++Func) { - if ((Method = dyn_cast<CXXMethodDecl>(*Func))) + if ((Method = dyn_cast<CXXMethodDecl>(*Func))) { + // If explicit template arguments were provided, we can't call a + // non-template member function. + if (MemExpr->hasExplicitTemplateArgumentList()) + continue; + AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet, /*SuppressUserConversions=*/false); - else + } else AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func), MemExpr->hasExplicitTemplateArgumentList(), MemExpr->getTemplateArgs(), diff --git a/test/SemaTemplate/member-template-access-expr.cpp b/test/SemaTemplate/member-template-access-expr.cpp index 0f9f21f339..feef7926fb 100644 --- a/test/SemaTemplate/member-template-access-expr.cpp +++ b/test/SemaTemplate/member-template-access-expr.cpp @@ -1,5 +1,4 @@ // RUN: clang-cc -fsyntax-only -verify %s - template<typename U, typename T> U f0(T t) { return t.template get<U>(); @@ -50,3 +49,29 @@ B<T>::destroy() void do_destroy_B(B<int> b) { b.destroy(); } + +struct X1 { + int* f1(int); + template<typename T> float* f1(T); + + static int* f2(int); + template<typename T> static float* f2(T); +}; + +void test_X1(X1 x1) { + float *fp1 = x1.f1<>(17); + float *fp2 = x1.f1<int>(3.14); + int *ip1 = x1.f1(17); + float *ip2 = x1.f1(3.14); + + float* (X1::*mf1)(int) = &X1::f1; + float* (X1::*mf2)(int) = &X1::f1<>; + float* (X1::*mf3)(float) = &X1::f1<float>; + + float* (*fp3)(int) = &X1::f2; + float* (*fp4)(int) = &X1::f2<>; + float* (*fp5)(float) = &X1::f2<float>; + float* (*fp6)(int) = X1::f2; + float* (*fp7)(int) = X1::f2<>; + float* (*fp8)(float) = X1::f2<float>; +} |