]> granicus.if.org Git - clang/commitdiff
Don't allow an rvalue reference to bind to the result of a calling a
authorDouglas Gregor <dgregor@apple.com>
Tue, 4 Oct 2011 23:59:32 +0000 (23:59 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 4 Oct 2011 23:59:32 +0000 (23:59 +0000)
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>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141137 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 836548aea7930c6765b4bf777f46400277a3bcc2..6174bbac73c5eec0aebb73c6f0828cbe5ca4aad0 100644 (file)
@@ -3324,6 +3324,16 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
       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 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
     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();
index a5a0d49afc4318c70d9fe1aabf988646fffd4d84..c1d34941d4c4809dbae52555cc85c83ad30bd72e 100644 (file)
@@ -17,7 +17,7 @@ int f(int);
 
 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 std_example_2 {
 
 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 @@ namespace argument_passing {
 
     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 @@ namespace pr10644 {
     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));
+  }
+}