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

Reply via email to