From: Douglas Gregor Date: Wed, 26 Jan 2011 19:41:18 +0000 (+0000) Subject: Rvalue references for *this: explicitly keep track of whether a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fcab48b626b7ce43625958e857061d721a43a5bc;p=clang Rvalue references for *this: explicitly keep track of whether a reference binding is for the implicit object parameter of a member function with a ref-qualifier. My previous comment, that we didn't need to track this explicitly, was wrong: we do in fact get rvalue-references-prefer-rvalues overloading with ref-qualifiers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124313 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 3d618689b2..fb7f5f129d 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -157,6 +157,10 @@ namespace clang { /// \brief Whether we're binding to an rvalue. unsigned BindsToRvalue : 1; + /// \brief Whether this binds an implicit object argument to a + /// non-static member function without a ref-qualifier. + unsigned BindsImplicitObjectArgumentWithoutRefQualifier : 1; + /// FromType - The type that this conversion is converting /// from. This is an opaque pointer that can be translated into a /// QualType. diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 62af5bb8ff..6d5eb8038d 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -173,6 +173,7 @@ void StandardConversionSequence::setAsIdentityConversion() { IsLvalueReference = true; BindsToFunctionLvalue = false; BindsToRvalue = false; + BindsImplicitObjectArgumentWithoutRefQualifier = false; CopyConstructor = 0; } @@ -2344,11 +2345,10 @@ static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1, // time of this writing) break the standard definition of std::forward // and std::reference_wrapper when dealing with references to functions. // Proposed wording changes submitted to CWG for consideration. - // - // Note: neither of these conditions will evalute true for the implicit - // object parameter, because we don't set either BindsToRvalue or - // BindsToFunctionLvalue when computing the conversion sequence for the - // implicit object parameter. + if (SCS1.BindsImplicitObjectArgumentWithoutRefQualifier || + SCS2.BindsImplicitObjectArgumentWithoutRefQualifier) + return false; + return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue && SCS2.IsLvalueReference) || (SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue && @@ -2994,6 +2994,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); ICS.Standard.BindsToRvalue = false; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.Standard.CopyConstructor = 0; // Nothing more to do: the inaccessibility/ambiguity check for @@ -3066,6 +3067,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); ICS.Standard.BindsToRvalue = InitCategory.isRValue(); + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.Standard.CopyConstructor = 0; return ICS; } @@ -3146,11 +3148,13 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); ICS.Standard.BindsToRvalue = true; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; } else if (ICS.isUserDefined()) { ICS.UserDefined.After.ReferenceBinding = true; ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); ICS.Standard.BindsToRvalue = true; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; } return ICS; @@ -3286,9 +3290,9 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, ICS.Standard.DirectBinding = true; ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue; ICS.Standard.BindsToFunctionLvalue = false; - - // Note: we intentionally don't set this; see isBetterReferenceBindingKind(). - ICS.Standard.BindsToRvalue = false; + ICS.Standard.BindsToRvalue = FromClassification.isRValue(); + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier + = (Method->getRefQualifier() == RQ_None); return ICS; } diff --git a/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp b/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp index 855895af98..8ccc5b6204 100644 --- a/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp +++ b/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp @@ -27,6 +27,8 @@ struct X0 { int &h() const&; float &h() &&; + int &h2() const&; + float &h2() const&&; }; void X0::g() { @@ -62,4 +64,7 @@ void test_ref_qualifier_overloading() { int &ir1 = lvalue().h(); float &fr1 = xvalue().h(); float &fr2 = prvalue().h(); + int &ir2 = lvalue().h2(); + float &fr3 = xvalue().h2(); + float &fr4 = prvalue().h2(); }