From: Douglas Gregor Date: Tue, 25 Jan 2011 19:39:31 +0000 (+0000) Subject: Fix the ranking of reference bindings during overload resolution X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=48a4ce7d484a448490edfe9e1d47b806cee85f30;p=clang Fix the ranking of reference bindings during overload resolution (C++0x [over.ics.rank]p3) when one binding is an lvalue reference and the other is an rvalue reference that binds to an rvalue. In particular, we were using the predict "is an rvalue reference" rather than "is an rvalue reference that binds to an rvalue", which was incorrect in the one case where an rvalue reference can bind to an lvalue: function references. This particular issue cropped up with std::forward, where Clang was picking an std::forward overload while forwarding an (lvalue) reference to a function. However (and unfortunately!), the right answer for this code is that the call to std::forward is ambiguous. Clang now gets that right, but we need to revisit the std::forward implementation in libc++. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124216 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index d32ff86953..85ae6f7326 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2966,7 +2966,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, ICS.Standard.setToType(2, T1); ICS.Standard.ReferenceBinding = true; ICS.Standard.DirectBinding = true; - ICS.Standard.RRefBinding = isRValRef; + ICS.Standard.RRefBinding = isRValRef && InitCategory.isRValue(); ICS.Standard.CopyConstructor = 0; // Nothing more to do: the inaccessibility/ambiguity check for @@ -3036,7 +3036,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, ICS.Standard.DirectBinding = S.getLangOptions().CPlusPlus0x || (InitCategory.isPRValue() && !T2->isRecordType()); - ICS.Standard.RRefBinding = isRValRef; + ICS.Standard.RRefBinding = isRValRef && InitCategory.isRValue(); ICS.Standard.CopyConstructor = 0; return ICS; } diff --git a/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp b/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp index cff9e9709a..faff058a50 100644 --- a/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp +++ b/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp @@ -15,7 +15,7 @@ namespace std_example { float &k2 = g2(f1()); float &l2 = g2(f2()); - // FIXME: We don't support ref-qualifiers set. + // FIXME: We don't support ref-qualifiers yet. #if 0 struct A { A& operator<<(int); @@ -33,3 +33,27 @@ namespace std_example { a.p(); #endif } + +template +struct remove_reference { + typedef T type; +}; + +template +struct remove_reference { + typedef T type; +}; + +template +struct remove_reference { + typedef T type; +}; + +namespace FunctionReferencesOverloading { + template int &f(typename remove_reference::type&); // expected-note{{candidate function [with T = int (&)(int)]}} + template float &f(typename remove_reference::type&&); // expected-note{{candidate function [with T = int (&)(int)]}} + + void test_f(int (&func_ref)(int)) { + f(func_ref); // expected-error{{call to 'f' is ambiguous}} + } +}