From: Faisal Vali Date: Sat, 15 Jun 2013 11:54:37 +0000 (+0000) Subject: A quick fix to allow return type deduction on member templates X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d570a9282fd1793cbf21c090d80cb0b6b4b89982;p=clang A quick fix to allow return type deduction on member templates by ensuring DiagnoseUseOfDecl is called both on the found decl and the decl being used (i.e the specialization in the case of member templates) whenever they are different. Per the exchange captured in http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130610/081636.html a more comprehensive fix that allows both decls to be passed into DiagnoseUseOfDecl is (or should be) forthcoming relatively soon. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184043 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index b9983ef055..5a40b1f8f2 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -43,8 +43,15 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, SourceLocation Loc = SourceLocation(), const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){ if (S.DiagnoseUseOfDecl(FoundDecl, Loc)) + return ExprError(); + // If FoundDecl is different from Fn (such as if one is a template + // and the other a specialization), make sure DiagnoseUseOfDecl is + // called on both. + // FIXME: This would be more comprehensively addressed by modifying + // DiagnoseUseOfDecl to accept both the FoundDecl and the decl + // being used. + if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc)) return ExprError(); - DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); if (HadMultipleCandidates) @@ -11001,6 +11008,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc())) return ExprError(); + // If FoundDecl is different from Method (such as if one is a template + // and the other a specialization), make sure DiagnoseUseOfDecl is + // called on both. + // FIXME: This would be more comprehensively addressed by modifying + // DiagnoseUseOfDecl to accept both the FoundDecl and the decl + // being used. + if (Method != FoundDecl.getDecl() && + DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc())) + return ExprError(); break; case OR_No_Viable_Function: @@ -11246,7 +11262,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); if (DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc)) return ExprError(); - + assert(Conv == Best->FoundDecl.getDecl() && + "Found Decl & conversion-to-functionptr should be same, right?!"); // We selected one of the surrogate functions that converts the // object parameter to a function pointer. Perform the conversion // on the object argument, then let ActOnCallExpr finish the job. diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp index eb6f6aaf9b..d3067eb411 100644 --- a/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -339,5 +339,37 @@ namespace ExplicitInstantiationDecl { extern template auto f(int); int (*p)(int) = f; } - +namespace MemberTemplatesWithDeduction { + struct M { + template auto foo(T t) { return t; } + template auto operator()(T t) const { return t; } + template static __attribute__((unused)) int static_foo(T) { + return 5; + } + template operator T() { return T{}; } + operator auto() { return &static_foo; } + }; + struct N : M { + using M::foo; + using M::operator(); + using M::static_foo; + using M::operator auto; + }; + + template int test() { + int i = T{}.foo(3); + T m = T{}.foo(M{}); + int j = T{}(3); + M m2 = M{}(M{}); + int k = T{}.static_foo(4); + int l = T::static_foo(5); + int l2 = T{}; + struct X { }; + X x = T{}; + return 0; + } + int Minst = test(); + int Ninst = test(); + +} }