summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-25 19:39:31 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-25 19:39:31 +0000
commit1c5a53e200c29b44907318ea22e31c0ae50f3d57 (patch)
treef364c42e4ff820874d07f0fdd8b632329e427ae7 /clang
parentade45d97038e907f94e9d9492f6b5cec58d3563c (diff)
downloadbcm5719-llvm-1c5a53e200c29b44907318ea22e31c0ae50f3d57.tar.gz
bcm5719-llvm-1c5a53e200c29b44907318ea22e31c0ae50f3d57.zip
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++. llvm-svn: 124216
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp4
-rw-r--r--clang/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp26
2 files changed, 27 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d32ff869534..85ae6f73260 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/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/clang/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp b/clang/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp
index cff9e9709a1..faff058a505 100644
--- a/clang/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp
+++ b/clang/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<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}}
+ }
+}
OpenPOWER on IntegriCloud