[cfe-commits] r123952 - in /cfe/trunk: lib/Sema/SemaInit.cpp test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp test/SemaCXX/rval-references.cpp

Douglas Gregor dgregor at apple.com
Thu Jan 20 16:52:42 PST 2011


Author: dgregor
Date: Thu Jan 20 18:52:42 2011
New Revision: 123952

URL: http://llvm.org/viewvc/llvm-project?rev=123952&view=rev
Log:
More work to bring reference binding up to the latest C++0x
specification. In particular, an rvalue reference can bind to an
initializer expression that is an lvalue if the referent type and the
initializer expression type are not reference-related. This is a newer
formulation to the previous "rvalue references can never bind to
lvalues" rule.

Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp
    cfe/trunk/test/SemaCXX/rval-references.cpp

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=123952&r1=123951&r2=123952&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jan 20 18:52:42 2011
@@ -2571,23 +2571,19 @@
   //     - Otherwise, the reference shall be an lvalue reference to a 
   //       non-volatile const type (i.e., cv1 shall be const), or the reference
   //       shall be an rvalue reference.
-  if (!((isLValueRef && T1Quals.hasConst() && !T1Quals.hasVolatile()) ||
-        (isRValueRef && InitCategory.isRValue()))) {
+  if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) {
     if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
       Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
     else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
       Sequence.SetOverloadFailure(
                         InitializationSequence::FK_ReferenceInitOverloadFailed,
                                   ConvOvlResult);
-    else if (isLValueRef)
+    else
       Sequence.SetFailed(InitCategory.isLValue()
         ? (RefRelationship == Sema::Ref_Related
              ? InitializationSequence::FK_ReferenceInitDropsQualifiers
              : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
         : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
-    else
-      Sequence.SetFailed(
-                    InitializationSequence::FK_RValueReferenceBindingToLValue);
 
     return;
   }
@@ -2696,6 +2692,15 @@
     return;
   }
 
+  //   [...] If T1 is reference-related to T2 and the reference is an rvalue 
+  //   reference, the initializer expression shall not be an lvalue.
+  if (RefRelationship >= Sema::Ref_Related && !isLValueRef && 
+      InitCategory.isLValue()) {
+    Sequence.SetFailed(
+                    InitializationSequence::FK_RValueReferenceBindingToLValue);
+    return;
+  }
+  
   Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
   return;
 }

Modified: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp?rev=123952&r1=123951&r2=123952&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp Thu Jan 20 18:52:42 2011
@@ -17,7 +17,7 @@
 
 template<typename T>
 struct ConvertsTo {
-  operator T();
+  operator T(); // expected-note 2{{candidate function}}
 };
 
 void test_rvalue_refs() {
@@ -56,6 +56,13 @@
 
   // function lvalue
   int (&&function1)(int) = ConvertsTo<int(&)(int)>();
+
+  // In the second case, if the reference is an rvalue reference and
+  // the second standard conversion sequence of the user-defined
+  // conversion sequence includes an lvalue-to-rvalue conversion, the
+  // program is ill-formed.
+  int &&int2 = ConvertsTo<int&>(); // expected-error{{no viable conversion from 'ConvertsTo<int &>' to 'int'}}
+  int &&int3 = ConvertsTo<float&>(); // expected-error{{no viable conversion from 'ConvertsTo<float &>' to 'int'}}
 }
 
 class NonCopyable {
@@ -81,3 +88,20 @@
   const NonCopyable &nc10 = ConvertsTo<NonCopyable&&>();
   const NonCopyable &nc11 = ConvertsTo<NonCopyableDerived&&>();
 }
+
+namespace std_example {
+  struct A { }; 
+  struct B : A { } b; 
+  extern B f(); 
+  const A& rca = f(); 
+  A&& rra = f();
+  struct X { 
+    operator B();  // expected-note{{candidate function}}
+    operator int&(); // expected-note{{candidate function}}
+  } x;
+  const A& r = x;
+  int i;
+  int&& rri = static_cast<int&&>(i);
+  B&& rrb = x;
+  int&& rri2 = X(); // expected-error{{no viable conversion from 'std_example::X' to 'int'}}
+}

Modified: cfe/trunk/test/SemaCXX/rval-references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/rval-references.cpp?rev=123952&r1=123951&r2=123952&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/rval-references.cpp (original)
+++ cfe/trunk/test/SemaCXX/rval-references.cpp Thu Jan 20 18:52:42 2011
@@ -47,7 +47,7 @@
   ilr_c2 vilr2 = i1;
 
   conv_to_not_int_rvalue cnir;
-  not_int &&ni4 = cnir; // expected-error {{rvalue reference cannot bind to lvalue}}
+  not_int &&ni4 = cnir;
   not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'not_int' cannot bind to a value of unrelated type 'conv_to_not_int_rvalue'}}
   not_int &&ni6 = conv_to_not_int_rvalue();
 





More information about the cfe-commits mailing list