[cfe-commits] r141137 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp

Douglas Gregor dgregor at apple.com
Tue Oct 4 16:59:45 PDT 2011


Author: dgregor
Date: Tue Oct  4 18:59:32 2011
New Revision: 141137

URL: http://llvm.org/viewvc/llvm-project?rev=141137&view=rev
Log:
Don't allow an rvalue reference to bind to the result of a calling a
conversion function whose result type is an lvalue reference. The
initialization code already handled this properly, but overload
resolution was allowing the binding. Fixes PR11003 /
<rdar://problem/10233078>.


Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=141137&r1=141136&r2=141137&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Oct  4 18:59:32 2011
@@ -3324,6 +3324,16 @@
       bool DerivedToBase = false;
       bool ObjCConversion = false;
       bool ObjCLifetimeConversion = false;
+      
+      // If we are initializing an rvalue reference, don't permit conversion
+      // functions that return lvalues.
+      if (!ConvTemplate && DeclType->isRValueReferenceType()) {
+        const ReferenceType *RefType
+          = Conv->getConversionType()->getAs<LValueReferenceType>();
+        if (RefType && !RefType->getPointeeType()->isFunctionType())
+          continue;
+      }
+      
       if (!ConvTemplate &&
           S.CompareReferenceRelationship(
             DeclLoc,
@@ -3643,6 +3653,19 @@
     ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
     ICS.Standard.ObjCLifetimeConversionBinding = false;
   } else if (ICS.isUserDefined()) {
+    // Don't allow rvalue references to bind to lvalues.
+    if (DeclType->isRValueReferenceType()) {
+      if (const ReferenceType *RefType
+            = ICS.UserDefined.ConversionFunction->getResultType()
+                ->getAs<LValueReferenceType>()) {
+        if (!RefType->getPointeeType()->isFunctionType()) {
+          ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, 
+                     DeclType);
+          return ICS;
+        }
+      }
+    }
+    
     ICS.UserDefined.After.ReferenceBinding = true;
     ICS.UserDefined.After.IsLvalueReference = !isRValRef;
     ICS.UserDefined.After.BindsToFunctionLvalue = T2->isFunctionType();

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=141137&r1=141136&r2=141137&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 Tue Oct  4 18:59:32 2011
@@ -17,7 +17,7 @@
 
 template<typename T>
 struct ConvertsTo {
-  operator T(); // expected-note 4{{candidate function}}
+  operator T(); // expected-note 2{{candidate function}}
 };
 
 void test_rvalue_refs() {
@@ -132,7 +132,9 @@
 
 namespace argument_passing {
   void base_rvalue_ref(Base&&);
-  void int_rvalue_ref(int&&); // expected-note 2{{passing argument to parameter here}}
+  void int_rvalue_ref(int&&); // expected-note{{candidate function not viable: no known conversion from 'ConvertsTo<int &>' to 'int &&' for 1st argument}} \
+  // expected-note{{candidate function not viable: no known conversion from 'ConvertsTo<float &>' to 'int &&' for 1st argument}}
+
   void array_rvalue_ref(int (&&)[5]);
   void function_rvalue_ref(int (&&)(int));
 
@@ -157,8 +159,8 @@
 
     function_rvalue_ref(ConvertsTo<int(&)(int)>());
     
-    int_rvalue_ref(ConvertsTo<int&>()); // expected-error{{no viable conversion from 'ConvertsTo<int &>' to 'int'}}
-    int_rvalue_ref(ConvertsTo<float&>()); // expected-error{{no viable conversion from 'ConvertsTo<float &>' to 'int'}}
+    int_rvalue_ref(ConvertsTo<int&>()); // expected-error{{no matching function for call to 'int_rvalue_ref'}}
+    int_rvalue_ref(ConvertsTo<float&>()); // expected-error{{no matching function for call to 'int_rvalue_ref'}}
   }
 
 }
@@ -177,3 +179,16 @@
     key_map["line"];
   }
 }
+
+namespace PR11003 {
+  class Value {
+  };
+  struct MoveRef {
+    operator Value &() const ;
+  };
+  MoveRef Move(int);
+  void growTo() {
+    Value x = Move(0);
+    Value y(Move(0));
+  }
+}





More information about the cfe-commits mailing list