Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -5178,9 +5178,11 @@ break; case RQ_LValue: - if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) - Diag(Loc, diag::err_pointer_to_member_oper_value_classify) - << RHSType << 1 << LHS.get()->getSourceRange(); + if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) { + if (!getLangOpts().CPlusPlus1z || !Proto->isConst()) + Diag(Loc, diag::err_pointer_to_member_oper_value_classify) + << RHSType << 1 << LHS.get()->getSourceRange(); + } break; case RQ_RValue: Index: test/CXX/expr/expr.mptr.oper/p7-1z.cpp =================================================================== --- test/CXX/expr/expr.mptr.oper/p7-1z.cpp +++ test/CXX/expr/expr.mptr.oper/p7-1z.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s + +struct X { }; + +template T& lvalue(); +template T&& xvalue(); +template T prvalue(); + +// In a .* expression whose object expression is an rvalue, the +// program is ill-formed if the second operand is a pointer to member +// function with (non-const, C++17) ref-qualifier &. +// In a ->* expression or in a .* expression whose object +// expression is an lvalue, the program is ill-formed if the second +// operand is a pointer to member function with ref-qualifier &&. +void test(X *xp, int (X::*pmf)(int), int (X::*l_pmf)(int) &, + int (X::*r_pmf)(int) &&, int (X::*cl_pmf)(int) const &, + int (X::*cr_pmf)(int) const &&) { + // No ref-qualifier. + (lvalue().*pmf)(17); + (xvalue().*pmf)(17); + (prvalue().*pmf)(17); + (xp->*pmf)(17); + + // Lvalue ref-qualifier. + (lvalue().*l_pmf)(17); + (xvalue().*l_pmf)(17); // expected-error-re{{pointer-to-member function type 'int (X::*)(int){{( __attribute__\(\(thiscall\)\))?}} &' can only be called on an lvalue}} + (prvalue().*l_pmf)(17); // expected-error-re{{pointer-to-member function type 'int (X::*)(int){{( __attribute__\(\(thiscall\)\))?}} &' can only be called on an lvalue}} + (xp->*l_pmf)(17); + + // Rvalue ref-qualifier. + (lvalue().*r_pmf)(17); // expected-error-re{{pointer-to-member function type 'int (X::*)(int){{( __attribute__\(\(thiscall\)\))?}} &&' can only be called on an rvalue}} + (xvalue().*r_pmf)(17); + (prvalue().*r_pmf)(17); + (xp->*r_pmf)(17); // expected-error-re{{pointer-to-member function type 'int (X::*)(int){{( __attribute__\(\(thiscall\)\))?}} &&' can only be called on an rvalue}} + + // Lvalue const ref-qualifier. + (lvalue().*cl_pmf)(17); + (xvalue().*cl_pmf)(17); + (prvalue().*cl_pmf)(17); + (xp->*cl_pmf)(17); + + // Rvalue const ref-qualifier. + (lvalue().*cr_pmf)(17); // expected-error-re{{pointer-to-member function type 'int (X::*)(int){{( __attribute__\(\(thiscall\)\))?}} const &&' can only be called on an rvalue}} + (xvalue().*cr_pmf)(17); + (prvalue().*cr_pmf)(17); + (xp->*cr_pmf)(17); // expected-error-re{{pointer-to-member function type 'int (X::*)(int){{( __attribute__\(\(thiscall\)\))?}} const &&' can only be called on an rvalue}} +}