diff options
| author | Douglas Gregor <dgregor@apple.com> | 2011-10-04 23:59:32 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2011-10-04 23:59:32 +0000 |
| commit | b0e6c8a3500c16f35bae030d5add46c942639ef7 (patch) | |
| tree | 4130998a6901a1df55e62cdd61b1880b3933b324 | |
| parent | 8569d2d8f2f0b9e98f56e9b150de1cd03db77e1f (diff) | |
| download | bcm5719-llvm-b0e6c8a3500c16f35bae030d5add46c942639ef7.tar.gz bcm5719-llvm-b0e6c8a3500c16f35bae030d5add46c942639ef7.zip | |
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>.
llvm-svn: 141137
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 23 | ||||
| -rw-r--r-- | clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp | 23 |
2 files changed, 42 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 836548aea79..6174bbac73c 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -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(); diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp index a5a0d49afc4..c1d34941d4c 100644 --- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp @@ -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)); + } +} |

