[cfe-commits] r101712 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/SemaCXX/overload-call.cpp

Douglas Gregor dgregor at apple.com
Sun Apr 18 02:22:01 PDT 2010


Author: dgregor
Date: Sun Apr 18 04:22:00 2010
New Revision: 101712

URL: http://llvm.org/viewvc/llvm-project?rev=101712&view=rev
Log:
When performing reference initialization for the purposes of overload
resolution ([over.ics.ref]), we take some shortcuts required by the
standard that effectively permit binding of a const volatile reference
to an rvalue. We have to treat lightly here to avoid infinite
recursion.

Fixes PR6177.


Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/overload-call.cpp

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=101712&r1=101711&r2=101712&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sun Apr 18 04:22:00 2010
@@ -2308,20 +2308,23 @@
   Sema::ReferenceCompareResult RefRelationship
     = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
 
-  // C++ [dcl.init.ref]p5:
-  //   A reference to type "cv1 T1" is initialized by an expression
-  //   of type "cv2 T2" as follows:
-
-  //     -- If the initializer expression
 
   // C++ [over.ics.ref]p3:
   //   Except for an implicit object parameter, for which see 13.3.1,
   //   a standard conversion sequence cannot be formed if it requires
   //   binding an lvalue reference to non-const to an rvalue or
   //   binding an rvalue reference to an lvalue.
+  //
+  // FIXME: DPG doesn't trust this code. It seems far too early to
+  // abort because of a binding of an rvalue reference to an lvalue.
   if (isRValRef && InitLvalue == Expr::LV_Valid)
     return ICS;
 
+  // C++0x [dcl.init.ref]p16:
+  //   A reference to type "cv1 T1" is initialized by an expression
+  //   of type "cv2 T2" as follows:
+
+  //     -- If the initializer expression
   //       -- is an lvalue (but is not a bit-field), and "cv1 T1" is
   //          reference-compatible with "cv2 T2," or
   //
@@ -2444,7 +2447,15 @@
   //     -- Otherwise, the reference shall be to a non-volatile const
   //        type (i.e., cv1 shall be const), or the reference shall be an
   //        rvalue reference and the initializer expression shall be an rvalue.
-  if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const)
+  // 
+  // We actually handle one oddity of C++ [over.ics.ref] at this
+  // point, which is that, due to p2 (which short-circuits reference
+  // binding by only attempting a simple conversion for non-direct
+  // bindings) and p3's strange wording, we allow a const volatile
+  // reference to bind to an rvalue. Hence the check for the presence
+  // of "const" rather than checking for "const" being the only
+  // qualifier.
+  if (!isRValRef && !T1.isConstQualified())
     return ICS;
 
   //       -- if T2 is a class type and
@@ -2508,7 +2519,6 @@
     return ICS;
 
   // C++ [over.ics.ref]p2:
-  //
   //   When a parameter of reference type is not bound directly to
   //   an argument expression, the conversion sequence is the one
   //   required to convert the argument expression to the

Modified: cfe/trunk/test/SemaCXX/overload-call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=101712&r1=101711&r2=101712&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overload-call.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-call.cpp Sun Apr 18 04:22:00 2010
@@ -247,14 +247,14 @@
 int& cvqual_subsume(X&); // expected-note{{candidate function}}
 float& cvqual_subsume(const Y&); // expected-note{{candidate function}}
 
-int& cvqual_subsume2(const X&);
-float& cvqual_subsume2(const volatile Y&);
+int& cvqual_subsume2(const X&); // expected-note{{candidate function}}
+float& cvqual_subsume2(const volatile Y&); // expected-note{{candidate function}}
 
 Z get_Z();
 
 void cvqual_subsume_test(Z z) {
   cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous; candidates are:}}
-  int& x = cvqual_subsume2(get_Z()); // okay: only binds to the first one
+  int& x = cvqual_subsume2(get_Z()); // expected-error{{call to 'cvqual_subsume2' is ambiguous; candidates are:}}
 }
 
 // Test overloading with cv-qualification differences in reference
@@ -421,3 +421,12 @@
     S()(0); // expected-error{{conversion from 'int' to 'PR6078::A' is ambiguous}}
   }
 }
+
+namespace PR6177 {
+  struct String { String(char const*); };
+
+  void f(bool const volatile&);
+  void f(String);
+
+  void g() { f(""); } // expected-error{{volatile lvalue reference to type 'bool const volatile' cannot bind to a value of unrelated type 'char const [1]'}}
+}





More information about the cfe-commits mailing list