Reference qualifiers for *this: implement C++0x [expr.mptr.oper]p6,
the restrictions on .* and ->* for ref-qualified pointer-to-member functions. llvm-svn: 124294
This commit is contained in:
parent
71711a673b
commit
1d042091d3
|
@ -1581,6 +1581,9 @@ def ext_template_arg_extra_parens : ExtWarn<
|
|||
"address non-type template argument cannot be surrounded by parentheses">;
|
||||
def err_pointer_to_member_type : Error<
|
||||
"invalid use of pointer to member type after %select{.*|->*}0">;
|
||||
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">;
|
||||
|
||||
// C++ template specialization
|
||||
def err_template_spec_unknown_kind : Error<
|
||||
|
|
|
@ -2557,6 +2557,32 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
|
|||
QualType Result = MemPtr->getPointeeType();
|
||||
Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
|
||||
|
||||
// C++0x [expr.mptr.oper]p6:
|
||||
// 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 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 &&.
|
||||
if (const FunctionProtoType *Proto = Result->getAs<FunctionProtoType>()) {
|
||||
switch (Proto->getRefQualifier()) {
|
||||
case RQ_None:
|
||||
// Do nothing
|
||||
break;
|
||||
|
||||
case RQ_LValue:
|
||||
if (!isIndirect && !lex->Classify(Context).isLValue())
|
||||
Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
|
||||
<< RType << 1 << lex->getSourceRange();
|
||||
break;
|
||||
|
||||
case RQ_RValue:
|
||||
if (isIndirect || !lex->Classify(Context).isRValue())
|
||||
Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
|
||||
<< RType << 0 << lex->getSourceRange();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// C++ [expr.mptr.oper]p6:
|
||||
// The result of a .* expression whose second operand is a pointer
|
||||
// to a data member is of the same value category as its
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||
|
||||
struct X { };
|
||||
|
||||
template<typename T> T& lvalue();
|
||||
template<typename T> T&& xvalue();
|
||||
template<typename T> 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 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) &&) {
|
||||
// No ref-qualifier.
|
||||
(lvalue<X>().*pmf)(17);
|
||||
(xvalue<X>().*pmf)(17);
|
||||
(prvalue<X>().*pmf)(17);
|
||||
(xp->*pmf)(17);
|
||||
|
||||
// Lvalue ref-qualifier.
|
||||
(lvalue<X>().*l_pmf)(17);
|
||||
(xvalue<X>().*l_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &' can only be called on an lvalue}}
|
||||
(prvalue<X>().*l_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &' can only be called on an lvalue}}
|
||||
(xp->*l_pmf)(17);
|
||||
|
||||
// Rvalue ref-qualifier.
|
||||
(lvalue<X>().*r_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &&' can only be called on an rvalue}}
|
||||
(xvalue<X>().*r_pmf)(17);
|
||||
(prvalue<X>().*r_pmf)(17);
|
||||
(xp->*r_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &&' can only be called on an rvalue}}
|
||||
}
|
Loading…
Reference in New Issue