[c++2a] P0704R1: Allow pointers to const& member functions to be called on rvalues.

Patch by Blitz Rakete!

llvm-svn: 311744
This commit is contained in:
Richard Smith 2017-08-25 01:47:55 +00:00
parent f5fb1e8bca
commit 2592327dae
4 changed files with 32 additions and 4 deletions

View File

@ -4088,6 +4088,13 @@ def err_pointer_to_member_call_drops_quals : Error<
def err_pointer_to_member_oper_value_classify: Error<
"pointer-to-member function type %0 can only be called on an "
"%select{rvalue|lvalue}1">;
def ext_pointer_to_const_ref_member_on_rvalue : Extension<
"invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension">,
InGroup<CXX2a>, SFINAEFailure;
def warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue : Warning<
"invoking a pointer to a 'const &' member function on an rvalue is "
"incompatible with C++ standards before C++2a">,
InGroup<CXXPre2aCompatPedantic>, DefaultIgnore;
def ext_ms_deref_template_argument: ExtWarn<
"non-type template argument containing a dereference operation is a "
"Microsoft extension">, InGroup<MicrosoftTemplate>;

View File

@ -5175,9 +5175,16 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
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()) {
// C++2a allows functions with ref-qualifier & if they are also 'const'.
if (Proto->isConst())
Diag(Loc, getLangOpts().CPlusPlus2a
? diag::warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue
: diag::ext_pointer_to_const_ref_member_on_rvalue);
else
Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
<< RHSType << 1 << LHS.get()->getSourceRange();
}
break;
case RQ_RValue:

View File

@ -0,0 +1,14 @@
// RUN: %clang_cc1 -std=c++2a %s -verify
struct X {
void ref() & {}
void cref() const& {}
};
void test() {
X{}.ref(); // expected-error{{cannot initialize object parameter of type 'X' with an expression of type 'X'}}
X{}.cref(); // expected-no-error
(X{}.*&X::ref)(); // expected-error{{pointer-to-member function type 'void (X::*)() &' can only be called on an lvalue}}
(X{}.*&X::cref)(); // expected-no-error
}

View File

@ -802,7 +802,7 @@ as the draft C++2a standard evolves.
<tr>
<td><tt>const&amp;</tt>-qualified pointers to members</td>
<td><a href="http://wg21.link/p0704r1">P0704R1</a></td>
<td class="none" align="center">No</td>
<td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Allow <i>lambda-capture</i> <tt>[=, this]</tt></td>