]> granicus.if.org Git - clang/commitdiff
Fix the ranking of reference bindings during overload resolution
authorDouglas Gregor <dgregor@apple.com>
Tue, 25 Jan 2011 19:39:31 +0000 (19:39 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 25 Jan 2011 19:39:31 +0000 (19:39 +0000)
(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

lib/Sema/SemaOverload.cpp
test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp

index d32ff869534b3f87d2bcee87137d112eb31b9114..85ae6f7326089a767e6544751ccfb30a429856f4 100644 (file)
@@ -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; 
   }
index cff9e9709a15c6f35e6c9a3b44b0f863032899d2..faff058a50526c9d69ae7f4567920237db0a1b6b 100644 (file)
@@ -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<typename T>
+struct remove_reference {
+  typedef T type;
+};
+
+template<typename T>
+struct remove_reference<T&> {
+  typedef T type;
+};
+
+template<typename T>
+struct remove_reference<T&&> {
+  typedef T type;
+};
+
+namespace FunctionReferencesOverloading {
+  template<typename T> int &f(typename remove_reference<T>::type&); // expected-note{{candidate function [with T = int (&)(int)]}}
+  template<typename T> float &f(typename remove_reference<T>::type&&); // expected-note{{candidate function [with T = int (&)(int)]}}
+
+  void test_f(int (&func_ref)(int)) {
+    f<int (&)(int)>(func_ref); // expected-error{{call to 'f' is ambiguous}}
+  }
+}