Hi, This patch series fixes a number of issues associated with bound member functions, fixing PR8793 among other things.
OK to commit? Thanks, -- Peter
>From 331f544927dc60862a1afa38b0b7d1eaa36dc98d Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <[email protected]> Date: Sat, 18 Dec 2010 23:29:02 +0000 Subject: [PATCH 1/7] Sema::BuildResolvedCallExpr: clean up pointee type checks --- lib/Sema/SemaExpr.cpp | 14 +++++--------- 1 files changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 01a505b..22a093c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4305,18 +4305,14 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, VK_RValue, RParenLoc); - const FunctionType *FuncT; - if (!Fn->getType()->isBlockPointerType()) { + const FunctionType *FuncT = 0; + if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) { // C99 6.5.2.2p1 - "The expression that denotes the called function shall // have type pointer to function". - const PointerType *PT = Fn->getType()->getAs<PointerType>(); - if (PT == 0) - return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) - << Fn->getType() << Fn->getSourceRange()); FuncT = PT->getPointeeType()->getAs<FunctionType>(); - } else { // This is a block call. - FuncT = Fn->getType()->getAs<BlockPointerType>()->getPointeeType()-> - getAs<FunctionType>(); + } else if (const BlockPointerType *BPT = Fn->getType()-> + getAs<BlockPointerType>()) { + FuncT = BPT->getPointeeType()->getAs<FunctionType>(); } if (FuncT == 0) return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) -- 1.7.1
>From c3afe20111c4310bd4e7ff17a4f6e1da75908ef4 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <[email protected]> Date: Sat, 18 Dec 2010 23:31:27 +0000 Subject: [PATCH 2/7] Sema::BuildResolvedCallExpr: move the nonstatic member function check earlier --- lib/Sema/SemaExpr.cpp | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 22a093c..863c3c3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4305,6 +4305,11 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, VK_RValue, RParenLoc); + if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl)) + if (!Method->isStatic()) + return ExprError(Diag(LParenLoc, diag::err_member_call_without_object) + << Fn->getSourceRange()); + const FunctionType *FuncT = 0; if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) { // C99 6.5.2.2p1 - "The expression that denotes the called function shall @@ -4383,11 +4388,6 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } } - if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl)) - if (!Method->isStatic()) - return ExprError(Diag(LParenLoc, diag::err_member_call_without_object) - << Fn->getSourceRange()); - // Check for sentinels if (NDecl) DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs); -- 1.7.1
>From 043a6dadda2bce48d99b3bf8382918611c6b3cae Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <[email protected]> Date: Sat, 18 Dec 2010 23:33:02 +0000 Subject: [PATCH 3/7] Sema::BuildCXXNamedCast: return early if bound member function found --- lib/Sema/SemaCXXCast.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index ac679f7..e13dd82 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -157,8 +157,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent(); if (Ex->isBoundMemberFunction(Context)) - Diag(Ex->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << Ex->getSourceRange(); + return Diag(Ex->getLocStart(), diag::err_invalid_use_of_bound_member_func) + << Ex->getSourceRange(); ExprValueKind VK = VK_RValue; if (TypeDependent) -- 1.7.1
>From 033599bb1eacf14f790c2b844684e13bcd73bd38 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <[email protected]> Date: Sat, 18 Dec 2010 23:36:58 +0000 Subject: [PATCH 4/7] Sema: recover from a->b where a of FunctionType --- lib/Sema/SemaExpr.cpp | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 863c3c3..d810b46 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3511,6 +3511,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, << BaseType << int(IsArrow) << BaseExpr->getSourceRange() << FixItHint::CreateReplacement(OpLoc, "."); IsArrow = false; + } else if (BaseType->isFunctionType()) { + goto fail; } else { Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) << BaseType << BaseExpr->getSourceRange(); -- 1.7.1
>From 596ce8057ebc42bcc08bf3a4f65397a708784869 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <[email protected]> Date: Sat, 18 Dec 2010 23:39:30 +0000 Subject: [PATCH 5/7] Sema: in C++, only perform function-pointer decay on lvalues (C++ 4.3p1). Fixes PR8793. --- lib/Sema/SemaExpr.cpp | 17 +++++++++++++---- test/SemaCXX/ptrtomember.cpp | 2 ++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d810b46..61bf396 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -223,10 +223,19 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { QualType Ty = E->getType(); assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type"); - if (Ty->isFunctionType()) - ImpCastExprToType(E, Context.getPointerType(Ty), - CK_FunctionToPointerDecay); - else if (Ty->isArrayType()) { + if (Ty->isFunctionType()) { + // C99 6.3.2.1p4: + // "A function designator is an expression that has function type... a + // function designator with type ``function returning type'' is converted + // to an expression that has type ``pointer to function returning type''." + // + // C++ 4.3p1: + // "An lvalue of function type T can be converted to an rvalue of type + // "pointer to T." The result is a pointer to the function." + if (!getLangOptions().CPlusPlus || E->isLValue()) + ImpCastExprToType(E, Context.getPointerType(Ty), + CK_FunctionToPointerDecay); + } else if (Ty->isArrayType()) { // In C90 mode, arrays only promote to pointers if the array expression is // an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has // type 'array of type' is converted to an expression that has type 'pointer diff --git a/test/SemaCXX/ptrtomember.cpp b/test/SemaCXX/ptrtomember.cpp index f26f13f..f5e4d2c 100644 --- a/test/SemaCXX/ptrtomember.cpp +++ b/test/SemaCXX/ptrtomember.cpp @@ -29,4 +29,6 @@ void f3(S3* p, void (S3::*m)()) { 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}} + + void (*mp)() = p ? p->m : p->m; // expected-error {{}} } -- 1.7.1
>From 26d96860d4dded8472ba5a97796dbfc867206d46 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <[email protected]> Date: Sun, 19 Dec 2010 00:26:51 +0000 Subject: [PATCH 6/7] Sema: use 'bound member function' diagnostic for unary operators --- lib/Sema/SemaExpr.cpp | 4 ++++ test/SemaCXX/ptrtomember.cpp | 3 +++ 2 files changed, 7 insertions(+), 0 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 61bf396..5de8f33 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -7804,6 +7804,10 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, Expr *Input) { UnaryOperatorKind Opc = static_cast<UnaryOperatorKind>(OpcIn); + if (Opc != UO_AddrOf && Input->isBoundMemberFunction(Context)) + return ExprError(Diag(OpLoc, diag::err_invalid_use_of_bound_member_func) + << Input->getSourceRange()); + ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; QualType resultType; diff --git a/test/SemaCXX/ptrtomember.cpp b/test/SemaCXX/ptrtomember.cpp index f5e4d2c..a9c3d88 100644 --- a/test/SemaCXX/ptrtomember.cpp +++ b/test/SemaCXX/ptrtomember.cpp @@ -31,4 +31,7 @@ void f3(S3* p, void (S3::*m)()) { p->m; // expected-error {{a bound member function may only be used to call it}} void (*mp)() = p ? p->m : p->m; // expected-error {{}} + (void)!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}} + mp = *p->m; // expected-error {{a bound member function may only be used to call it}} } -- 1.7.1
>From 6e02068b5c7b67c8d0377fd363d8c4c3df982e9c Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <[email protected]> Date: Sun, 19 Dec 2010 00:27:42 +0000 Subject: [PATCH 7/7] Sema: diagnose sizeof operations whose operand is a bound member function --- lib/Sema/SemaExpr.cpp | 4 ++++ test/SemaCXX/ptrtomember.cpp | 1 + 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5de8f33..ae2e22a 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2640,6 +2640,10 @@ Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, } else if (E->getBitField()) { // C99 6.5.3.4p1. Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0; isInvalid = true; + } else if (E->isBoundMemberFunction(Context)) { + Diag(OpLoc, diag::err_invalid_use_of_bound_member_func) + << E->getSourceRange(); + isInvalid = true; } else if (E->getType()->isPlaceholderType()) { ExprResult PE = CheckPlaceholderExpr(E, OpLoc); if (PE.isInvalid()) return ExprError(); diff --git a/test/SemaCXX/ptrtomember.cpp b/test/SemaCXX/ptrtomember.cpp index a9c3d88..5e75713 100644 --- a/test/SemaCXX/ptrtomember.cpp +++ b/test/SemaCXX/ptrtomember.cpp @@ -34,4 +34,5 @@ void f3(S3* p, void (S3::*m)()) { (void)!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}} mp = *p->m; // expected-error {{a bound member function may only be used to call it}} + (void)sizeof(p->m); // expected-error {{a bound member function may only be used to call it}} } -- 1.7.1
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
