forked from OSchip/llvm-project
Emit error when using a bound member function for something other than calling it.
Also avoids IRGen crashes due to accepting invalid code. llvm-svn: 117943
This commit is contained in:
parent
b524d906fe
commit
ca76629618
|
@ -396,6 +396,9 @@ public:
|
|||
/// write barrier.
|
||||
bool isOBJCGCCandidate(ASTContext &Ctx) const;
|
||||
|
||||
/// \brief Returns true if this expression is a bound member function.
|
||||
bool isBoundMemberFunction(ASTContext &Ctx) const;
|
||||
|
||||
/// \brief Result type of CanThrow().
|
||||
enum CanThrowResult {
|
||||
CT_Cannot,
|
||||
|
|
|
@ -2641,6 +2641,8 @@ def err_not_tag_in_scope : Error<
|
|||
|
||||
def err_cannot_form_pointer_to_member_of_reference_type : Error<
|
||||
"cannot form a pointer-to-member to member %0 of reference type %1">;
|
||||
def err_invalid_use_of_bound_member_func : Error<
|
||||
"a bound member function may only be used to call it">;
|
||||
def err_incomplete_object_call : Error<
|
||||
"incomplete type in call to object of type %0">;
|
||||
def err_incomplete_pointer_to_member_return : Error<
|
||||
|
|
|
@ -1324,6 +1324,12 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
|
|||
}
|
||||
}
|
||||
|
||||
bool Expr::isBoundMemberFunction(ASTContext &Ctx) const {
|
||||
if (isTypeDependent())
|
||||
return false;
|
||||
return isLvalue(Ctx) == Expr::LV_MemberFunction;
|
||||
}
|
||||
|
||||
static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1,
|
||||
Expr::CanThrowResult CT2) {
|
||||
// CanThrowResult constants are ordered so that the maximum is the correct
|
||||
|
|
|
@ -146,6 +146,10 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
|||
// FIXME: should we check this in a more fine-grained manner?
|
||||
bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent();
|
||||
|
||||
if (Ex->isBoundMemberFunction(Context))
|
||||
Diag(Ex->getLocStart(), diag::err_invalid_use_of_bound_member_func)
|
||||
<< Ex->getSourceRange();
|
||||
|
||||
switch (Kind) {
|
||||
default: assert(0 && "Unknown C++ cast!");
|
||||
|
||||
|
@ -1273,6 +1277,11 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
|
|||
CastKind &Kind,
|
||||
CXXCastPath &BasePath,
|
||||
bool FunctionalStyle) {
|
||||
if (CastExpr->isBoundMemberFunction(Context))
|
||||
return Diag(CastExpr->getLocStart(),
|
||||
diag::err_invalid_use_of_bound_member_func)
|
||||
<< CastExpr->getSourceRange();
|
||||
|
||||
// This test is outside everything else because it's the only case where
|
||||
// a non-lvalue-reference target type does not lead to decay.
|
||||
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
|
||||
|
|
|
@ -8206,6 +8206,10 @@ bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) {
|
|||
DiagnoseAssignmentAsCondition(E);
|
||||
|
||||
if (!E->isTypeDependent()) {
|
||||
if (E->isBoundMemberFunction(Context))
|
||||
return Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
|
||||
<< E->getSourceRange();
|
||||
|
||||
DefaultFunctionArrayLvalueConversion(E);
|
||||
|
||||
QualType T = E->getType();
|
||||
|
|
|
@ -74,6 +74,12 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
|
|||
if (!E)
|
||||
return;
|
||||
|
||||
if (E->isBoundMemberFunction(Context)) {
|
||||
Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
|
||||
<< E->getSourceRange();
|
||||
return;
|
||||
}
|
||||
|
||||
SourceLocation Loc;
|
||||
SourceRange R1, R2;
|
||||
if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
|
||||
|
|
|
@ -16,3 +16,17 @@ struct S2 {
|
|||
};
|
||||
|
||||
int S2::*pf = &S2::bitfield; // expected-error {{address of bit-field requested}}
|
||||
|
||||
struct S3 {
|
||||
void m();
|
||||
};
|
||||
|
||||
void f3(S3* p, void (S3::*m)()) {
|
||||
p->*m; // expected-error {{a bound member function may only be used to call it}}
|
||||
(void)(p->*m); // expected-error {{a bound member function may only be used to call it}}
|
||||
(void)(void*)(p->*m); // expected-error {{a bound member function may only be used to call it}}
|
||||
(void)reinterpret_cast<void*>(p->*m); // expected-error {{a bound member function may only be used to call it}}
|
||||
if (p->*m) {} // expected-error {{a bound member function may only be used to call it}}
|
||||
|
||||
p->m; // expected-error {{a bound member function may only be used to call it}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue