llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Yingwei Zheng (dtcxzyw)

<details>
<summary>Changes</summary>

This patch adds support for GCC bound member functions extension: 
https://gcc.gnu.org/onlinedocs/gcc/Bound-member-functions.html

Closes https://github.com/llvm/llvm-project/issues/82727

---

Patch is 29.68 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/135649.diff


19 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+5) 
- (modified) clang/include/clang/AST/OperationKinds.def (+4) 
- (modified) clang/include/clang/Basic/DiagnosticGroups.td (+16-16) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+1) 
- (modified) clang/lib/AST/Expr.cpp (+7) 
- (modified) clang/lib/AST/ExprConstant.cpp (+2) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+1) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+1) 
- (modified) clang/lib/CodeGen/CGExprAgg.cpp (+2) 
- (modified) clang/lib/CodeGen/CGExprComplex.cpp (+1) 
- (modified) clang/lib/CodeGen/CGExprConstant.cpp (+1) 
- (modified) clang/lib/CodeGen/CGExprScalar.cpp (+32) 
- (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+20-2) 
- (modified) clang/lib/Edit/RewriteObjCFoundationAPI.cpp (+1) 
- (modified) clang/lib/Sema/SemaCast.cpp (+40-20) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp (+2-1) 
- (added) clang/test/CodeGenCXX/pmf-conversions.cpp (+105) 
- (added) clang/test/SemaCXX/pmf-conversions.cpp (+54) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5af4c08f64cd8..768497712ecd6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -96,6 +96,11 @@ C++ Language Changes
       asm((std::string_view("nop")) ::: (std::string_view("memory")));
     }
 
+- Implemented `GCC bound member functions extension 
<https://gcc.gnu.org/onlinedocs/gcc/Bound-member-functions.html>`_ for Itanium 
ABI.
+  This extension allows extracting the function pointer from a bound pointer 
to member function.
+  It is useful to save vtable lookups when the same member function is 
executed multiple times inside a loop.
+  When using this extension, a warning is emitted unless 
``-Wno-pmf-conversions`` is passed.
+
 C++2c Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/include/clang/AST/OperationKinds.def 
b/clang/include/clang/AST/OperationKinds.def
index 790dd572a7c99..489d89a697dc3 100644
--- a/clang/include/clang/AST/OperationKinds.def
+++ b/clang/include/clang/AST/OperationKinds.def
@@ -152,6 +152,10 @@ CAST_OPERATION(MemberPointerToBoolean)
 /// many ABIs do not guarantee this on all possible intermediate types).
 CAST_OPERATION(ReinterpretMemberPointer)
 
+/// CK_BoundPointerToMemberFunctionToFunctionPointer - Convert a bound
+/// member function pointer to a function pointer.  This is a GNU extension.
+CAST_OPERATION(BoundMemberFunctionToFunctionPointer)
+
 /// CK_UserDefinedConversion - Conversion using a user defined type
 /// conversion function.
 ///    struct A { operator int(); }; int i = int(A());
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index d97bbfee2e4d5..8e5a4cba87c95 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -795,6 +795,7 @@ def DuplicateDeclSpecifier : 
DiagGroup<"duplicate-decl-specifier">;
 def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
 def GNUUnionCast : DiagGroup<"gnu-union-cast">;
 def GNUVariableSizedTypeNotAtEnd : 
DiagGroup<"gnu-variable-sized-type-not-at-end">;
+def GNUPMFCast : DiagGroup<"pmf-conversions">;
 def Varargs : DiagGroup<"varargs">;
 def XorUsedAsPow : DiagGroup<"xor-used-as-pow">;
 
@@ -1294,22 +1295,21 @@ def C2y : DiagGroup<"c2y-extensions">;
 def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
 
 // A warning group for warnings about GCC extensions.
-def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
-                            GNUAutoType, GNUBinaryLiteral, GNUCaseRange,
-                            GNUComplexInteger, GNUCompoundLiteralInitializer,
-                            GNUConditionalOmittedOperand, GNUDesignator,
-                            GNUEmptyStruct,
-                            VLAExtension, GNUFlexibleArrayInitializer,
-                            GNUFlexibleArrayUnionMember, GNUFoldingConstant,
-                            GNUImaginaryConstant, GNUIncludeNext,
-                            GNULabelsAsValue, GNULineMarker, 
GNUNullPointerArithmetic,
-                            GNUOffsetofExtensions, GNUPointerArith,
-                            RedeclaredClassMember, GNURedeclaredEnum,
-                            GNUStatementExpression, GNUStaticFloatInit,
-                            GNUStringLiteralOperatorTemplate, GNUUnionCast,
-                            GNUVariableSizedTypeNotAtEnd, ZeroLengthArray,
-                            GNUZeroLineDirective,
-                            GNUZeroVariadicMacroArguments]>;
+def GNU
+    : DiagGroup<
+          "gnu", [GNUAlignofExpression, GNUAnonymousStruct, GNUAutoType,
+                  GNUBinaryLiteral, GNUCaseRange, GNUComplexInteger,
+                  GNUCompoundLiteralInitializer, GNUConditionalOmittedOperand,
+                  GNUDesignator, GNUEmptyStruct, VLAExtension,
+                  GNUFlexibleArrayInitializer, GNUFlexibleArrayUnionMember,
+                  GNUFoldingConstant, GNUImaginaryConstant, GNUIncludeNext,
+                  GNULabelsAsValue, GNULineMarker, GNUNullPointerArithmetic,
+                  GNUOffsetofExtensions, GNUPointerArith, 
RedeclaredClassMember,
+                  GNURedeclaredEnum, GNUStatementExpression, 
GNUStaticFloatInit,
+                  GNUStringLiteralOperatorTemplate, GNUUnionCast,
+                  GNUVariableSizedTypeNotAtEnd, ZeroLengthArray,
+                  GNUZeroLineDirective, GNUZeroVariadicMacroArguments,
+                  GNUPMFCast]>;
 // A warning group for warnings about code that clang accepts but gcc doesn't.
 def GccCompat : DiagGroup<"gcc-compat">;
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3f7499d8656bd..5c882df7fcbdf 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5144,6 +5144,10 @@ def err_ovl_unresolvable : Error<
 def err_bound_member_function : Error<
   "reference to non-static member function must be called"
   "%select{|; did you mean to call it with no arguments?}0">;
+def ext_bound_member_function_conversion
+    : ExtWarn<"converting the bound member function %1 to a function pointer "
+              "%2 is a GNU extension">,
+      InGroup<GNUPMFCast>;
 def note_possible_target_of_call : Note<"possible target for call">;
 def err_no_viable_destructor : Error<
   "no viable destructor found for class %0">;
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 0d3c2065cd58c..7dc299827916b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -109,6 +109,7 @@ def CK_ArrayToPointerDecay : 
I32EnumAttrCase<"array_to_ptrdecay", 11>;
 // CK_DerivedToBaseMemberPointer
 def CK_MemberPointerToBoolean : I32EnumAttrCase<"member_ptr_to_bool", 17>;
 // CK_ReinterpretMemberPointer
+// CK_BoundMemberFunctionToFunctionPointer
 // CK_UserDefinedConversion
 // CK_ConstructorConversion
 def CK_IntegralToPointer : I32EnumAttrCase<"int_to_ptr", 21>;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 59c0e47c7c195..e42d626acacb6 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1864,6 +1864,13 @@ bool CastExpr::CastConsistency() const {
     assert(getSubExpr()->getType()->isMemberPointerType());
     goto CheckNoBasePath;
 
+  case CK_BoundMemberFunctionToFunctionPointer:
+    assert(getType()->isFunctionPointerType());
+    assert(getSubExpr()->getType()->isMemberPointerType() ||
+           getSubExpr()->getType()->isSpecificPlaceholderType(
+               BuiltinType::BoundMember));
+    goto CheckNoBasePath;
+
   case CK_BitCast:
     // Arbitrary casts to C pointer types count as bitcasts.
     // Otherwise, we should only have block and ObjC pointer casts
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d1cc722fb7945..b104a4e9416c0 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -15103,6 +15103,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) 
{
   case CK_BaseToDerivedMemberPointer:
   case CK_DerivedToBaseMemberPointer:
   case CK_ReinterpretMemberPointer:
+  case CK_BoundMemberFunctionToFunctionPointer:
   case CK_ConstructorConversion:
   case CK_IntegralToPointer:
   case CK_ToVoid:
@@ -15960,6 +15961,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr 
*E) {
   case CK_DerivedToBaseMemberPointer:
   case CK_MemberPointerToBoolean:
   case CK_ReinterpretMemberPointer:
+  case CK_BoundMemberFunctionToFunctionPointer:
   case CK_ConstructorConversion:
   case CK_IntegralToPointer:
   case CK_PointerToIntegral:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index cffe5c5cd1ec3..1c4a06ad8d61d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -83,6 +83,7 @@ Address CIRGenFunction::emitPointerWithAlignment(const Expr 
*expr,
     case CK_NullToMemberPointer:
     case CK_NullToPointer:
     case CK_ReinterpretMemberPointer:
+    case CK_BoundMemberFunctionToFunctionPointer:
       // Common pointer conversions, nothing to do here.
       // TODO: Is there any reason to treat base-to-derived conversions
       // specially?
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index abb88477062fc..bf22a62d20c11 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5417,6 +5417,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) 
{
   case CK_BaseToDerivedMemberPointer:
   case CK_MemberPointerToBoolean:
   case CK_ReinterpretMemberPointer:
+  case CK_BoundMemberFunctionToFunctionPointer:
   case CK_AnyPointerToBlockPointerCast:
   case CK_ARCProduceObject:
   case CK_ARCConsumeObject:
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 87b2a73fb0c03..91fdf8a072111 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -1043,6 +1043,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
   case CK_DerivedToBaseMemberPointer:
   case CK_MemberPointerToBoolean:
   case CK_ReinterpretMemberPointer:
+  case CK_BoundMemberFunctionToFunctionPointer:
   case CK_IntegralToPointer:
   case CK_PointerToIntegral:
   case CK_PointerToBoolean:
@@ -1600,6 +1601,7 @@ static bool castPreservesZero(const CastExpr *CE) {
   case CK_MemberPointerToBoolean:
   case CK_NullToMemberPointer:
   case CK_ReinterpretMemberPointer:
+  case CK_BoundMemberFunctionToFunctionPointer:
     // FIXME: ABI-dependent.
     return false;
 
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp 
b/clang/lib/CodeGen/CGExprComplex.cpp
index f556594f4a9ec..008082a493a2a 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -575,6 +575,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, 
Expr *Op,
   case CK_DerivedToBaseMemberPointer:
   case CK_MemberPointerToBoolean:
   case CK_ReinterpretMemberPointer:
+  case CK_BoundMemberFunctionToFunctionPointer:
   case CK_ConstructorConversion:
   case CK_IntegralToPointer:
   case CK_PointerToIntegral:
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp 
b/clang/lib/CodeGen/CGExprConstant.cpp
index b21ebeee4bed1..ca3a2cd9af3dd 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1272,6 +1272,7 @@ class ConstExprEmitter
       llvm_unreachable("builtin functions are handled elsewhere");
 
     case CK_ReinterpretMemberPointer:
+    case CK_BoundMemberFunctionToFunctionPointer:
     case CK_DerivedToBaseMemberPointer:
     case CK_BaseToDerivedMemberPointer: {
       auto C = Emitter.tryEmitPrivate(subExpr, subExpr->getType());
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 8dbbcdaef25d8..fa64df8be8c27 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2628,6 +2628,38 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
     return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT);
   }
 
+  case CK_BoundMemberFunctionToFunctionPointer: {
+    // Special handling bound member functions
+    if (E->isBoundMemberFunction(CGF.getContext())) {
+      auto *BO = cast<BinaryOperator>(E->IgnoreParens());
+      const Expr *BaseExpr = BO->getLHS();
+      const Expr *MemFnExpr = BO->getRHS();
+
+      const auto *MPT = MemFnExpr->getType()->castAs<MemberPointerType>();
+      const auto *FPT = MPT->getPointeeType()->castAs<FunctionProtoType>();
+      const auto *RD = MPT->getMostRecentCXXRecordDecl();
+
+      // Emit the 'this' pointer.
+      Address This = Address::invalid();
+      if (BO->getOpcode() == BO_PtrMemI)
+        This = CGF.EmitPointerWithAlignment(BaseExpr, nullptr, nullptr,
+                                            KnownNonNull);
+      else
+        This = CGF.EmitLValue(BaseExpr, KnownNonNull).getAddress();
+
+      // Get the member function pointer.
+      llvm::Value *MemFnPtr = CGF.EmitScalarExpr(MemFnExpr);
+
+      // Ask the ABI to load the callee.  Note that This is modified.
+      llvm::Value *ThisPtrForCall = nullptr;
+      CGCallee Callee = CGF.CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(
+          CGF, BO, This, ThisPtrForCall, MemFnPtr, MPT);
+      return Callee.getFunctionPointer();
+    }
+
+    // fallback to the case without the base object address
+  }
+    [[fallthrough]];
   case CK_ReinterpretMemberPointer:
   case CK_BaseToDerivedMemberPointer:
   case CK_DerivedToBaseMemberPointer: {
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 70b53be7e77a3..6e4732ea977a9 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -926,7 +926,8 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction 
&CGF,
 
   assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
          E->getCastKind() == CK_BaseToDerivedMemberPointer ||
-         E->getCastKind() == CK_ReinterpretMemberPointer);
+         E->getCastKind() == CK_ReinterpretMemberPointer ||
+         E->getCastKind() == CK_BoundMemberFunctionToFunctionPointer);
 
   CGBuilderTy &Builder = CGF.Builder;
   QualType DstType = E->getType();
@@ -973,6 +974,8 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction 
&CGF,
 
   // Under Itanium, reinterprets don't require any additional processing.
   if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
+  if (E->getCastKind() == CK_BoundMemberFunctionToFunctionPointer)
+    return Builder.CreateExtractValue(src, 0, "src.ptr");
 
   llvm::Constant *adj = getMemberPointerAdjustment(E);
   if (!adj) return src;
@@ -1047,7 +1050,8 @@ ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr 
*E,
                                            llvm::Constant *src) {
   assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
          E->getCastKind() == CK_BaseToDerivedMemberPointer ||
-         E->getCastKind() == CK_ReinterpretMemberPointer);
+         E->getCastKind() == CK_ReinterpretMemberPointer ||
+         E->getCastKind() == CK_BoundMemberFunctionToFunctionPointer);
 
   QualType DstType = E->getType();
 
@@ -1057,6 +1061,20 @@ ItaniumCXXABI::EmitMemberPointerConversion(const 
CastExpr *E,
 
   // Under Itanium, reinterprets don't require any additional processing.
   if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
+  if (E->getCastKind() == CK_BoundMemberFunctionToFunctionPointer) {
+    llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
+    llvm::Constant *FuncPtr = llvm::ConstantExpr::getIntToPtr(
+        ConstantFoldExtractValueInstruction(src, 0), PtrTy);
+
+    const auto &NewAuthInfo = CGM.getFunctionPointerAuthInfo(DstType);
+    const auto &CurAuthInfo =
+        CGM.getMemberFunctionPointerAuthInfo(E->getSubExpr()->getType());
+
+    if (!NewAuthInfo && !CurAuthInfo)
+      return FuncPtr;
+
+    return pointerAuthResignConstant(FuncPtr, CurAuthInfo, NewAuthInfo, CGM);
+  }
 
   // If the adjustment is trivial, we don't need to do anything.
   llvm::Constant *adj = getMemberPointerAdjustment(E);
diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp 
b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
index 627a1d6fb3dd5..51f1de0edae4b 100644
--- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
+++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -1054,6 +1054,7 @@ static bool rewriteToNumericBoxedExpression(const 
ObjCMessageExpr *Msg,
     case CK_DerivedToBaseMemberPointer:
     case CK_MemberPointerToBoolean:
     case CK_ReinterpretMemberPointer:
+    case CK_BoundMemberFunctionToFunctionPointer:
     case CK_ConstructorConversion:
     case CK_IntegralToPointer:
     case CK_PointerToIntegral:
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 14e16bc39eb3a..fe1e485cc92a6 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -153,6 +153,11 @@ namespace {
     bool isPlaceholder(BuiltinType::Kind K) const {
       return PlaceholderKind == K;
     }
+    bool isBoundPMFConversion() const {
+      return isPlaceholder(BuiltinType::BoundMember) &&
+             DestType->isFunctionPointerType() &&
+             SrcExpr.get()->isBoundMemberFunction(Self.Context);
+    }
 
     // Language specific cast restrictions for address spaces.
     void checkAddressSpaceCast(QualType SrcType, QualType DestType);
@@ -254,13 +259,11 @@ static TryCastResult TryStaticDowncast(Sema &Self, 
CanQualType SrcType,
                                        QualType OrigDestType, unsigned &msg,
                                        CastKind &Kind,
                                        CXXCastPath &BasePath);
-static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult 
&SrcExpr,
-                                               QualType SrcType,
-                                               QualType DestType,bool CStyle,
-                                               SourceRange OpRange,
-                                               unsigned &msg,
-                                               CastKind &Kind,
-                                               CXXCastPath &BasePath);
+static TryCastResult
+TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
+                             QualType DestType, bool CStyle,
+                             SourceRange OpRange, unsigned &msg, CastKind 
&Kind,
+                             CXXCastPath &BasePath);
 
 static TryCastResult
 TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
@@ -1234,9 +1237,10 @@ static unsigned int checkCastFunctionType(Sema &Self, 
const ExprResult &SrcExpr,
 /// like this:
 /// char *bytes = reinterpret_cast\<char*\>(int_ptr);
 void CastOperation::CheckReinterpretCast() {
-  if (ValueKind == VK_PRValue && !isPlaceholder(BuiltinType::Overload))
-    SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
-  else
+  if (ValueKind == VK_PRValue) {
+    if (!isPlaceholder(BuiltinType::Overload) && !isBoundPMFConversion())
+      SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
+  } else
     checkNonOverloadPlaceholders();
   if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
     return;
@@ -2363,6 +2367,16 @@ static TryCastResult TryReinterpretCast(Sema &Self, 
ExprResult &SrcExpr,
     return TC_Success;
   }
 
+  // GNU extension: check if we can convert a pmf to a function pointer
+  if (DestType->isFunctionPointerType() &&
+      (SrcType->isMemberFunctionPointerType() ||
+       SrcExpr.get()->isBoundMemberFunction(Self.Context)) &&
+      Self.Context.getTargetInfo().getCXXABI().isItaniumFamily()) {
+    Kind = CK_BoundMemberFunctionToFunctionPointer;
+    msg = diag::ext_bound_member_function_conversion;
+    return TC_Extension;
+  }
+
   // See below for the enumeral issue.
   if (SrcType->isNullPtrType() && DestType->isIntegralType(Self.Context)) {
     // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral
@@ -2729,9 +2743,11 @@ void CastOperation::CheckCXXCStyleCast(bool 
FunctionalStyle,
       return;
     }
 
-    checkNonOverloadPlaceholders();
-    if (SrcExpr.isInvalid())
-      return;
+    if (!isBoundPMFConversion()) {
+      checkNonOverloadPlaceholders();
+      if (SrcExpr.isInvalid())
+        return;
+    }
   }
 
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
@@ -2769,7 +2785,7 @@ void CastOperation::CheckCXXCStyleCast(bool 
FunctionalStyle,
   }
 
   if (ValueKind == VK_PRValue && !DestType->isRecordType() &&
-      !isPlaceholder(BuiltinType::Overload)) {
+      !isPlaceholder(BuiltinType::Overload) && !isBoundPMFConversion()) {
     SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
     if (SrcExpr.isInvalid())
       return;
@@ -2827,12 +2843,16 @@ void CastOperation::CheckCXXCStyleCast(bool 
FunctionalStyle,
       return;
 
     if (tcr == TC_NotApplicable) {
-      // ... or if that is not possible, a static_cast, ignoring const and
-      // addr space, ...
-      tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange, msg, Kind,
-                          BasePath, ListInitialization);
-      if (SrcExpr.isInvalid())
-        return;
+      // FIXME: Bound member function to function pointer conversion is blocked
+      // by an immediat...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/135649
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to