Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -5472,8 +5472,9 @@ case RQ_LValue: if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) { - // C++2a allows functions with ref-qualifier & if they are also 'const'. - if (Proto->isConst()) + // C++2a allows functions with ref-qualifier & if their cv-qualifier-seq + // is (exactly) 'const'. + if (Proto->isConst() && !Proto->isVolatile()) Diag(Loc, getLangOpts().CPlusPlus2a ? diag::warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue : diag::ext_pointer_to_const_ref_member_on_rvalue); Index: test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp =================================================================== --- test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp +++ test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp @@ -3,12 +3,15 @@ struct X { void ref() & {} // expected-note{{'ref' declared here}} void cref() const& {} + void cvref() const volatile & {} // expected-note{{'cvref' declared here}} }; void test() { X{}.ref(); // expected-error{{'this' argument to member function 'ref' is an rvalue, but function has non-const lvalue ref-qualifier}} X{}.cref(); // expected-no-error + X{}.cvref(); // expected-error{{'this' argument to member function 'cvref' is an rvalue, but function has non-const lvalue ref-qualifier}} (X{}.*&X::ref)(); // expected-error-re{{pointer-to-member function type 'void (X::*)() {{.*}}&' can only be called on an lvalue}} (X{}.*&X::cref)(); // expected-no-error + (X{}.*&X::cvref)(); // expected-error-re{{pointer-to-member function type 'void (X::*)() {{.*}}&' can only be called on an lvalue}} }