diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-24 16:14:37 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-24 16:14:37 +0000 |
commit | 8dde14e7f43a4b29e592b3e8e576eb467ddb6c6e (patch) | |
tree | 926ec6608ecc240a7101b0f595d33840afb6f75f /lib/Sema/SemaOverload.cpp | |
parent | 274f83c2ece9041a1994fc3eacfe812ca86095e8 (diff) |
Re-instate r123977/r123978, my updates of the reference-binding
implementation used by overload resolution to support rvalue
references. The original commits caused PR9026 and some
hard-to-reproduce self-host breakage.
The only (crucial!) difference between this commit and the previous
commits is that we now properly check the SuppressUserConversions flag
before attempting to perform a second user-defined conversion in
reference binding, breaking the infinite recursion chain of
user-defined conversions.
Rvalue references should be working a bit better now.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124121 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 132 |
1 files changed, 57 insertions, 75 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 1a50841e3a..d32ff86953 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2798,10 +2798,6 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, CXXRecordDecl *T2RecordDecl = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); - QualType ToType - = AllowRvalues? DeclType->getAs<ReferenceType>()->getPointeeType() - : DeclType; - OverloadCandidateSet CandidateSet(DeclLoc); const UnresolvedSetImpl *Conversions = T2RecordDecl->getVisibleConversionFunctions(); @@ -2852,10 +2848,10 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, - Init, ToType, CandidateSet); + Init, DeclType, CandidateSet); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, - ToType, CandidateSet); + DeclType, CandidateSet); } OverloadCandidateSet::iterator Best; @@ -2944,9 +2940,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // of type "cv2 T2" as follows: // -- If reference is an lvalue reference and the initializer expression - // The next bullet point (T1 is a function) is pretty much equivalent to this - // one, so it's handled here. - if (!isRValRef || T1->isFunctionType()) { + if (!isRValRef) { // -- is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or // @@ -3001,8 +2995,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // -- 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 and the initializer expression shall be - // an rvalue or have a function type. + // shall be an rvalue reference. // // We actually handle one oddity of C++ [over.ics.ref] at this // point, which is that, due to p2 (which short-circuits reference @@ -3016,73 +3009,62 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, if (!isRValRef && !T1.isConstQualified()) return ICS; - // -- If T1 is a function type, then - // -- if T2 is the same type as T1, the reference is bound to the - // initializer expression lvalue; - // -- if T2 is a class type and the initializer expression can be - // implicitly converted to an lvalue of type T1 [...], the - // reference is bound to the function lvalue that is the result - // of the conversion; - // This is the same as for the lvalue case above, so it was handled there. - // -- otherwise, the program is ill-formed. - // This is the one difference to the lvalue case. - if (T1->isFunctionType()) - return ICS; - - // -- Otherwise, if T2 is a class type and - // -- the initializer expression is an rvalue and "cv1 T1" - // is reference-compatible with "cv2 T2," or + // -- If the initializer expression // - // -- T1 is not reference-related to T2 and the initializer - // expression can be implicitly converted to an rvalue - // of type "cv3 T3" (this conversion is selected by - // enumerating the applicable conversion functions - // (13.3.1.6) and choosing the best one through overload - // resolution (13.3)), + // -- is an xvalue, class prvalue, array prvalue or function + // lvalue and "cv1T1" is reference-compatible with "cv2 T2", or + if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification && + (InitCategory.isXValue() || + (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) || + (InitCategory.isLValue() && T2->isFunctionType()))) { + ICS.setStandard(); + ICS.Standard.First = ICK_Identity; + ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base + : ObjCConversion? ICK_Compatible_Conversion + : ICK_Identity; + ICS.Standard.Third = ICK_Identity; + ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); + ICS.Standard.setToType(0, T2); + ICS.Standard.setToType(1, T1); + ICS.Standard.setToType(2, T1); + ICS.Standard.ReferenceBinding = true; + // In C++0x, this is always a direct binding. In C++98/03, it's a direct + // binding unless we're binding to a class prvalue. + // Note: Although xvalues wouldn't normally show up in C++98/03 code, we + // allow the use of rvalue references in C++98/03 for the benefit of + // standard library implementors; therefore, we need the xvalue check here. + ICS.Standard.DirectBinding = + S.getLangOptions().CPlusPlus0x || + (InitCategory.isPRValue() && !T2->isRecordType()); + ICS.Standard.RRefBinding = isRValRef; + ICS.Standard.CopyConstructor = 0; + return ICS; + } + + // -- has a class type (i.e., T2 is a class type), where T1 is not + // reference-related to T2, and can be implicitly converted to + // an xvalue, class prvalue, or function lvalue of type + // "cv3 T3", where "cv1 T1" is reference-compatible with + // "cv3 T3", // - // then the reference is bound to the initializer - // expression rvalue in the first case and to the object - // that is the result of the conversion in the second case - // (or, in either case, to the appropriate base class - // subobject of the object). - if (T2->isRecordType()) { - // First case: "cv1 T1" is reference-compatible with "cv2 T2". This is a - // direct binding in C++0x but not in C++03. - if (InitCategory.isRValue() && - RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { - ICS.setStandard(); - ICS.Standard.First = ICK_Identity; - ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base - : ObjCConversion? ICK_Compatible_Conversion - : ICK_Identity; - ICS.Standard.Third = ICK_Identity; - ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); - ICS.Standard.setToType(0, T2); - ICS.Standard.setToType(1, T1); - ICS.Standard.setToType(2, T1); - ICS.Standard.ReferenceBinding = true; - ICS.Standard.DirectBinding = S.getLangOptions().CPlusPlus0x; - ICS.Standard.RRefBinding = isRValRef; - ICS.Standard.CopyConstructor = 0; - return ICS; - } - - // Second case: not reference-related. - if (RefRelationship == Sema::Ref_Incompatible && - !S.RequireCompleteType(DeclLoc, T2, 0) && - FindConversionForRefInit(S, ICS, DeclType, DeclLoc, - Init, T2, /*AllowRvalues=*/true, - AllowExplicit)) { - // 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. - if (ICS.isUserDefined() && isRValRef && - ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue) - ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); + // then the reference is bound to the value of the initializer + // expression in the first case and to the result of the conversion + // in the second case (or, in either case, to an appropriate base + // class subobject). + if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible && + T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) && + FindConversionForRefInit(S, ICS, DeclType, DeclLoc, + Init, T2, /*AllowRvalues=*/true, + AllowExplicit)) { + // 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. + if (ICS.isUserDefined() && isRValRef && + ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue) + ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); - return ICS; - } + return ICS; } // -- Otherwise, a temporary of type "cv1 T1" is created and |