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:
Argyrios Kyrtzidis 2010-11-01 18:49:26 +00:00
parent b524d906fe
commit ca76629618
7 changed files with 44 additions and 0 deletions

View File

@ -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,

View File

@ -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<

View File

@ -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

View File

@ -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".

View File

@ -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();

View File

@ -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))

View File

@ -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}}
}