diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 4b13c556cb..61cb9587d6 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1574,7 +1574,11 @@ public: CK_FloatingToIntegral, /// CK_FloatingCast - Casting between floating types of different size. - CK_FloatingCast + CK_FloatingCast, + + /// CK_MemberPointerToBoolean - Member pointer to boolean + CK_MemberPointerToBoolean + }; private: diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 7c80f04be2..34790d27d2 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -556,6 +556,8 @@ const char *CastExpr::getCastKindName() const { return "FloatingToIntegral"; case CastExpr::CK_FloatingCast: return "FloatingCast"; + case CastExpr::CK_MemberPointerToBoolean: + return "MemberPointerToBoolean"; } assert(0 && "Unhandled cast kind!"); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 5c6657c6c7..fce4f111a9 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -901,6 +901,35 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) { return Yay; } + case CastExpr::CK_MemberPointerToBoolean: { + const MemberPointerType* T = E->getType()->getAs(); + + if (T->getPointeeType()->isFunctionType()) { + // We have a member function pointer. + llvm::Value *Ptr = CGF.CreateTempAlloca(ConvertType(E->getType())); + + CGF.EmitAggExpr(E, Ptr, /*VolatileDest=*/false); + + // Get the pointer. + llvm::Value *FuncPtr = Builder.CreateStructGEP(Ptr, 0, "src.ptr"); + FuncPtr = Builder.CreateLoad(FuncPtr); + + llvm::Value *IsNotNull = + Builder.CreateICmpNE(FuncPtr, + llvm::Constant::getNullValue(FuncPtr->getType()), + "tobool"); + + return IsNotNull; + } + + // We have a regular member pointer. + Value *Ptr = Visit(const_cast(E)); + llvm::Value *IsNotNull = + Builder.CreateICmpNE(Ptr, CGF.CGM.EmitNullConstant(E->getType()), + "tobool"); + return IsNotNull; + } + } // Handle cases where the source is an non-complex type. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 24fd6c5eeb..21ab093a1a 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1359,9 +1359,14 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, ImpCastExprToType(From, ToType, Kind); break; } - case ICK_Boolean_Conversion: - ImpCastExprToType(From, Context.BoolTy, CastExpr::CK_Unknown); + case ICK_Boolean_Conversion: { + CastExpr::CastKind Kind = CastExpr::CK_Unknown; + if (FromType->isMemberPointerType()) + Kind = CastExpr::CK_MemberPointerToBoolean; + + ImpCastExprToType(From, Context.BoolTy, Kind); break; + } case ICK_Derived_To_Base: if (CheckDerivedToBaseConversion(From->getType(), diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp index 7792560e06..56696712e4 100644 --- a/test/CodeGenCXX/member-function-pointers.cpp +++ b/test/CodeGenCXX/member-function-pointers.cpp @@ -55,6 +55,10 @@ void f3(A *a, A &ar) { (ar.*pa)(); } +bool f4() { + return pa; +} + // PR5177 namespace PR5177 { struct A {