Hi! (Sorry for the resent, forgot to CC gcc-patches).
Another easy C++2A patch. Here I wonder if we don't want a -Wc++2a-compat warning and whether & (const | volatile)) == const is best (for the case if there are other quals in the future), or if we just want == const. For the compat warning, the behavior will be that for c++17 and below we'll error out or fail SFINAE, for c++2a we'll accept it, so not sure if it falls into what we want to warn or not. Regtested on x86_64-linux and i686-linux with make check-c++-all. 2017-09-19 Jakub Jelinek <ja...@redhat.com> P0704R1 - fixing const-qualified pointers to members * typeck2.c (build_m_component_ref): For -std=c++2a allow pointer to const & qualified method on rvalue. * g++.dg/cpp2a/ptrmem1.C: New test. --- gcc/cp/typeck2.c.jj 2017-09-19 12:06:30.635052397 +0200 +++ gcc/cp/typeck2.c 2017-09-19 12:12:50.725235890 +0200 @@ -1908,9 +1908,10 @@ build_m_component_ref (tree datum, tree { /* 5.5/6: 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 ref-qualifier &. 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 &&. */ + function with ref-qualifier & (for C++2A: unless its cv-qualifier-seq + is const). 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 &&. */ if (FUNCTION_REF_QUALIFIED (type)) { bool lval = lvalue_p (datum); @@ -1921,7 +1922,12 @@ build_m_component_ref (tree datum, tree ptrmem_type); return error_mark_node; } - else if (!lval && !FUNCTION_RVALUE_QUALIFIED (type)) + else if (!lval + && !FUNCTION_RVALUE_QUALIFIED (type) + && (cxx_dialect < cxx2a + || ((type_memfn_quals (type) + & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) + != TYPE_QUAL_CONST))) { if (complain & tf_error) error ("pointer-to-member-function type %qT requires an lvalue", --- gcc/testsuite/g++.dg/cpp2a/ptrmem1.C.jj 2017-09-19 12:30:49.344545579 +0200 +++ gcc/testsuite/g++.dg/cpp2a/ptrmem1.C 2017-09-19 12:33:40.831363371 +0200 @@ -0,0 +1,23 @@ +// P0704R1 +// { dg-do compile { target c++11 } } + +struct S { + void ref() & {} + void cref() const& {} + void vref() volatile & {} + void cvref() const volatile & {} +}; + +void +foo () +{ + S{}.ref(); // { dg-error "argument discards qualifiers" } + S{}.cref(); + S{}.vref(); // { dg-error "argument discards qualifiers" } + S{}.cvref(); // { dg-error "argument discards qualifiers" } + + (S{}.*&S::ref)(); // { dg-error "pointer-to-member-function type 'void \\(S::\\*\\)\\(\\) &' requires an lvalue" } + (S{}.*&S::cref)(); // { dg-error "pointer-to-member-function type 'void \\(S::\\*\\)\\(\\) const &' requires an lvalue" "" { target c++17_down } } + (S{}.*&S::vref)(); // { dg-error "pointer-to-member-function type 'void \\(S::\\*\\)\\(\\) volatile &' requires an lvalue" } + (S{}.*&S::cvref)(); // { dg-error "pointer-to-member-function type 'void \\(S::\\*\\)\\(\\) const volatile &' requires an lvalue" } +} Jakub