https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/135649

>From 6795a5143129520d2db343d768507174a70da453 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2...@gmail.com>
Date: Tue, 15 Apr 2025 01:24:10 +0800
Subject: [PATCH 1/2] [Clang] Add support for GCC bound member functions
 extension

---
 clang/include/clang/AST/ExprCXX.h             | 37 +++++++++++
 clang/include/clang/AST/RecursiveASTVisitor.h |  4 ++
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 +
 .../include/clang/Serialization/ASTBitCodes.h |  3 +
 clang/lib/AST/ExprConstant.cpp                |  6 ++
 clang/lib/AST/StmtPrinter.cpp                 | 12 ++++
 clang/lib/AST/StmtProfile.cpp                 |  8 +++
 clang/lib/Sema/SemaCast.cpp                   | 64 +++++++++++++++++++
 clang/lib/Sema/TreeTransform.h                | 35 ++++++++++
 clang/lib/Serialization/ASTReaderStmt.cpp     | 16 +++++
 clang/lib/Serialization/ASTWriterStmt.cpp     |  7 ++
 11 files changed, 195 insertions(+)

diff --git a/clang/include/clang/AST/ExprCXX.h 
b/clang/include/clang/AST/ExprCXX.h
index 844f6dd90ae1d..7918ea0b20d41 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -5448,6 +5448,43 @@ class BuiltinBitCastExpr final
   }
 };
 
+/// Represents a GCC extension bound pointer-to-member-function -> function
+/// pointer conversion.
+class BoundPointerToMemberFunctionToFunctionPointerCastExpr final
+    : public ExplicitCastExpr,
+      private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> {
+  friend class ASTStmtReader;
+  friend class CastExpr;
+
+  Expr *BaseExpr;
+
+public:
+  BoundPointerToMemberFunctionToFunctionPointerCastExpr(
+      QualType T, ExprValueKind VK, CastKind CK, Expr *SrcExpr,
+      TypeSourceInfo *DstType, Expr *BaseExpr)
+      : ExplicitCastExpr(
+            BoundPointerToMemberFunctionToFunctionPointerCastExprClass, T, VK,
+            CK, SrcExpr, 0, false, DstType),
+        BaseExpr(BaseExpr) {}
+
+  BoundPointerToMemberFunctionToFunctionPointerCastExpr(EmptyShell Empty)
+      : ExplicitCastExpr(BuiltinBitCastExprClass, Empty, 0, false) {}
+
+  Expr *getBaseExpr() const LLVM_READONLY { return BaseExpr; }
+
+  SourceLocation getBeginLoc() const LLVM_READONLY {
+    return BaseExpr ? BaseExpr->getBeginLoc() : getSubExpr()->getBeginLoc();
+  }
+  SourceLocation getEndLoc() const LLVM_READONLY {
+    return getSubExpr()->getEndLoc();
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() ==
+           BoundPointerToMemberFunctionToFunctionPointerCastExprClass;
+  }
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_AST_EXPRCXX_H
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h 
b/clang/include/clang/AST/RecursiveASTVisitor.h
index 3edc8684d0a19..e917f468b322f 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2567,6 +2567,10 @@ DEF_TRAVERSE_STMT(BuiltinBitCastExpr, {
   TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
 })
 
+DEF_TRAVERSE_STMT(BoundPointerToMemberFunctionToFunctionPointerCastExpr, {
+  TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
+
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
     InitListExpr *S, DataRecursionQueue *Queue) {
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 180ca39bc07e9..5f5d53c968bbc 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5120,6 +5120,9 @@ 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 warn_bound_member_function_conversion
+    : Warning<
+          "converting the bound member function %0 to a function pointer %1">;
 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/Serialization/ASTBitCodes.h 
b/clang/include/clang/Serialization/ASTBitCodes.h
index 5cb9998126a85..98ec32d0e5b98 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1869,6 +1869,9 @@ enum StmtCode {
   /// A BuiltinBitCastExpr record.
   EXPR_BUILTIN_BIT_CAST,
 
+  /// A BoundPointerToMemberFunctionToFunctionPointerCastExpr record.
+  EXPR_PMF_CAST,
+
   /// A UserDefinedLiteral record.
   EXPR_USER_DEFINED_LITERAL,
 
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d1cc722fb7945..4382bb05e7b97 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8121,6 +8121,10 @@ class ExprEvaluatorBase
   bool VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E) {
     return static_cast<Derived*>(this)->VisitCastExpr(E);
   }
+  bool VisitBoundPointerToMemberFunctionToFunctionPointerCastExpr(
+      const BoundPointerToMemberFunctionToFunctionPointerCastExpr *E) {
+    return static_cast<Derived *>(this)->VisitCastExpr(E);
+  }
 
   bool VisitBinaryOperator(const BinaryOperator *E) {
     switch (E->getOpcode()) {
@@ -17662,6 +17666,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext 
&Ctx) {
       return ICEDiag(IK_NotICE, E->getBeginLoc());
     return CheckICE(cast<CastExpr>(E)->getSubExpr(), Ctx);
   }
+  case Expr::BoundPointerToMemberFunctionToFunctionPointerCastExprClass:
+    return ICEDiag(IK_NotICE, E->getBeginLoc());
   }
 
   llvm_unreachable("Invalid StmtClass!");
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index dbe2432d5c799..d515314be4efa 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -2135,6 +2135,18 @@ void 
StmtPrinter::VisitBuiltinBitCastExpr(BuiltinBitCastExpr *Node) {
   OS << ")";
 }
 
+void StmtPrinter::VisitBoundPointerToMemberFunctionToFunctionPointerCastExpr(
+    BoundPointerToMemberFunctionToFunctionPointerCastExpr *Node) {
+  OS << "(";
+  Node->getTypeAsWritten().print(OS, Policy);
+  OS << ")";
+  if (auto *Base = Node->getBaseExpr()) {
+    PrintExpr(Base);
+    OS << ".*";
+  }
+  PrintExpr(Node->getSubExpr());
+}
+
 void StmtPrinter::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *Node) {
   VisitCXXNamedCastExpr(Node);
 }
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 83d54da9be7e5..efb68c7bf78e6 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2014,6 +2014,14 @@ void StmtProfiler::VisitBuiltinBitCastExpr(const 
BuiltinBitCastExpr *S) {
   VisitType(S->getTypeInfoAsWritten()->getType());
 }
 
+void StmtProfiler::VisitBoundPointerToMemberFunctionToFunctionPointerCastExpr(
+    const BoundPointerToMemberFunctionToFunctionPointerCastExpr *S) {
+  VisitExpr(S);
+  VisitType(S->getTypeInfoAsWritten()->getType());
+  if (auto *Base = S->getBaseExpr())
+    VisitExpr(Base);
+}
+
 void StmtProfiler::VisitCXXAddrspaceCastExpr(const CXXAddrspaceCastExpr *S) {
   VisitCXXNamedCastExpr(S);
 }
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 2824dfce1572c..308d541c1dd9e 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -250,6 +250,10 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema 
&Self, ExprResult &SrcExp
                                                unsigned &msg,
                                                CastKind &Kind,
                                                CXXCastPath &BasePath);
+static TryCastResult TryStaticMemberFunctionPointerToFunctionPointerCast(
+    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,
@@ -1430,6 +1434,13 @@ static TryCastResult TryStaticCast(Sema &Self, 
ExprResult &SrcExpr,
     }
   }
 
+  // GCC extension: convert a PMF constant into a function pointer.
+  tcr = TryStaticMemberFunctionPointerToFunctionPointerCast(
+      Self, SrcExpr, SrcType, DestType, CStyle, OpRange, msg, Kind, BasePath);
+
+  if (tcr != TC_NotApplicable)
+    return tcr;
+
   // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast.
   // C++ 5.2.9p8 additionally disallows a cast path through virtual 
inheritance.
   tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg,
@@ -1834,6 +1845,59 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult 
&SrcExpr, QualType SrcType,
   return TC_Success;
 }
 
+/// TryStaticMemberFunctionPointerToFunctionPointerCast - Tests whether a
+/// conversion from PMF constant to function pointer is valid.
+TryCastResult TryStaticMemberFunctionPointerToFunctionPointerCast(
+    Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestType,
+    bool CStyle, SourceRange OpRange, unsigned &msg, CastKind &Kind,
+    CXXCastPath &BasePath) {
+  const TargetCXXABI &CXXABI = Self.Context.getTargetInfo().getCXXABI();
+  if (!CXXABI.isItaniumFamily())
+    return TC_NotApplicable;
+
+  const PointerType *DestPtr = DestType->getAs<PointerType>();
+  if (!DestPtr)
+    return TC_NotApplicable;
+
+  const FunctionProtoType *DestFnType =
+      DestPtr->getPointeeType()->getAs<FunctionProtoType>();
+  if (!DestFnType || DestFnType->getNumParams() == 0)
+    return TC_NotApplicable;
+
+  auto *ClsPtr = DestFnType->getParamType(0)->getAs<PointerType>();
+  if (!ClsPtr)
+    return TC_NotApplicable;
+
+  auto *ClsRec = ClsPtr->getPointeeType()->getAs<RecordType>();
+  if (!ClsRec)
+    return TC_NotApplicable;
+
+  auto *ClsTy = ClsRec->getAsCXXRecordDecl();
+  if (!ClsTy)
+    return TC_NotApplicable;
+
+  auto EPI = DestFnType->getExtProtoInfo();
+  EPI.TypeQuals = ClsPtr->getPointeeType().getQualifiers();
+  auto FuncTy =
+      Self.Context.getFunctionType(DestFnType->getCallResultType(Self.Context),
+                                   DestFnType->param_types().drop_front(), 
EPI);
+  auto DestPMFTy = Self.Context.getMemberPointerType(FuncTy, nullptr, ClsTy);
+
+  ExprResult Result = SrcExpr;
+
+  if (SrcType.getCanonicalType() != DestPMFTy) {
+    TryCastResult Res = TryStaticMemberPointerUpcast(
+        Self, Result, SrcType, DestType, CStyle, OpRange, msg, Kind, BasePath);
+    if (Res == TC_NotApplicable)
+      return TC_NotApplicable;
+  }
+
+  DestPMFTy->dump();
+
+  // SrcExpr = Result;
+  return TC_NotApplicable;
+}
+
 /// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2
 /// is valid:
 ///
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index bb58ec49612c8..41d3c9aad3d54 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3329,6 +3329,16 @@ class TreeTransform {
     return getSema().BuildBuiltinBitCastExpr(KWLoc, TSI, Sub, RParenLoc);
   }
 
+  /// Build a new C++ bound pointer-to-member-function to function pointer
+  /// conversion expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildBoundPointerToMemberFunctionToFunctionPointerCastExpr(
+      TypeSourceInfo *TSI, Expr *Sub, Expr *Base) {
+    return ExprError();
+  }
+
   /// Build a new C++ typeid(type) expression.
   ///
   /// By default, performs semantic analysis to build the new expression.
@@ -14175,6 +14185,31 @@ 
TreeTransform<Derived>::TransformBuiltinBitCastExpr(BuiltinBitCastExpr *BCE) {
                                                 Sub.get(), BCE->getEndLoc());
 }
 
+template <typename Derived>
+ExprResult TreeTransform<Derived>::
+    TransformBoundPointerToMemberFunctionToFunctionPointerCastExpr(
+        BoundPointerToMemberFunctionToFunctionPointerCastExpr *E) {
+  TypeSourceInfo *TSI = getDerived().TransformType(E->getTypeInfoAsWritten());
+  if (!TSI)
+    return ExprError();
+
+  ExprResult Sub = getDerived().TransformExpr(E->getSubExpr());
+  if (Sub.isInvalid())
+    return ExprError();
+
+  auto *Base = E->getBaseExpr();
+  if (Base) {
+    ExprResult NewBase = getDerived().TransformExpr(Base);
+    if (NewBase.isInvalid())
+      return ExprError();
+    Base = NewBase.get();
+  }
+
+  return getDerived()
+      .RebuildBoundPointerToMemberFunctionToFunctionPointerCastExpr(
+          TSI, Sub.get(), Base);
+}
+
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) {
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp 
b/clang/lib/Serialization/ASTReaderStmt.cpp
index f41cfcc53a35d..a9445e6623970 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1846,6 +1846,12 @@ void 
ASTStmtReader::VisitBuiltinBitCastExpr(BuiltinBitCastExpr *E) {
   E->RParenLoc = readSourceLocation();
 }
 
+void ASTStmtReader::VisitBoundPointerToMemberFunctionToFunctionPointerCastExpr(
+    BoundPointerToMemberFunctionToFunctionPointerCastExpr *E) {
+  VisitExplicitCastExpr(E);
+  E->BaseExpr = Record.readSubExpr();
+}
+
 void ASTStmtReader::VisitUserDefinedLiteral(UserDefinedLiteral *E) {
   VisitCallExpr(E);
   E->UDSuffixLoc = readSourceLocation();
@@ -4150,6 +4156,16 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
       break;
     }
 
+    case EXPR_PMF_CAST: {
+#ifndef NDEBUG
+      unsigned PathSize = Record[ASTStmtReader::NumExprFields];
+      assert(PathSize == 0 && "Wrong PathSize!");
+#endif
+      S = new (Context)
+          BoundPointerToMemberFunctionToFunctionPointerCastExpr(Empty);
+      break;
+    }
+
     case EXPR_USER_DEFINED_LITERAL: {
       auto NumArgs = Record[ASTStmtReader::NumExprFields];
       BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields + 1]);
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp 
b/clang/lib/Serialization/ASTWriterStmt.cpp
index b9eabd5ddb64c..46413f917cf07 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1839,6 +1839,13 @@ void 
ASTStmtWriter::VisitBuiltinBitCastExpr(BuiltinBitCastExpr *E) {
   Code = serialization::EXPR_BUILTIN_BIT_CAST;
 }
 
+void ASTStmtWriter::VisitBoundPointerToMemberFunctionToFunctionPointerCastExpr(
+    BoundPointerToMemberFunctionToFunctionPointerCastExpr *E) {
+  VisitExplicitCastExpr(E);
+  Record.AddStmt(E->getBaseExpr());
+  Code = serialization::EXPR_PMF_CAST;
+}
+
 void ASTStmtWriter::VisitUserDefinedLiteral(UserDefinedLiteral *E) {
   VisitCallExpr(E);
   Record.AddSourceLocation(E->UDSuffixLoc);

>From ad35c72575b8b3cfd2dde1060be7500309f2bea8 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2...@gmail.com>
Date: Tue, 15 Apr 2025 09:36:30 +0800
Subject: [PATCH 2/2] Update

---
 clang/include/clang-c/Index.h          | 5 +++++
 clang/include/clang/Basic/StmtNodes.td | 1 +
 clang/tools/libclang/CIndex.cpp        | 3 +++
 clang/tools/libclang/CXCursor.cpp      | 3 +++
 4 files changed, 12 insertions(+)

diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 38e2417dcd181..dce77eef6ec6c 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2218,6 +2218,11 @@ enum CXCursorKind {
    */
   CXCursor_OpenACCCacheConstruct = 333,
 
+  /** GNU C++ bound pointer to member function to function pointer cast
+   * expression.
+   */
+  CXCursor_BoundPointerToMemberFunctionToFunctionPointerCastExpr = 334,
+
   CXCursor_LastStmt = CXCursor_OpenACCCacheConstruct,
 
   /**
diff --git a/clang/include/clang/Basic/StmtNodes.td 
b/clang/include/clang/Basic/StmtNodes.td
index 9526fa5808aa5..1e3681785905b 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -113,6 +113,7 @@ def AddrLabelExpr : StmtNode<Expr>;
 def StmtExpr : StmtNode<Expr>;
 def ChooseExpr : StmtNode<Expr>;
 def GNUNullExpr : StmtNode<Expr>;
+def BoundPointerToMemberFunctionToFunctionPointerCastExpr : 
StmtNode<ExplicitCastExpr>;
 
 // C++ Expressions.
 def CXXOperatorCallExpr : StmtNode<CallExpr>;
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index c8db6c92bb4d4..bdc14232dd52e 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -22,6 +22,7 @@
 #include "CXType.h"
 #include "CursorVisitor.h"
 #include "clang-c/FatalErrorHandler.h"
+#include "clang-c/Index.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/AttrVisitor.h"
 #include "clang/AST/DeclObjCCommon.h"
@@ -6501,6 +6502,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind 
Kind) {
     return cxstring::createRef("OpenACCUpdateConstruct");
   case CXCursor_OpenACCAtomicConstruct:
     return cxstring::createRef("OpenACCAtomicConstruct");
+  case CXCursor_BoundPointerToMemberFunctionToFunctionPointerCastExpr:
+    return 
cxstring::createRef("BoundPointerToMemberFunctionToFunctionPointerCastExpr");
   }
 
   llvm_unreachable("Unhandled CXCursorKind");
diff --git a/clang/tools/libclang/CXCursor.cpp 
b/clang/tools/libclang/CXCursor.cpp
index 1d15120106017..162af05bd7600 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -937,6 +937,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl 
*Parent,
   case Stmt::OMPAssumeDirectiveClass:
     K = CXCursor_OMPAssumeDirective;
     break;
+  case Stmt::BoundPointerToMemberFunctionToFunctionPointerCastExprClass:
+    K = CXCursor_BoundPointerToMemberFunctionToFunctionPointerCastExpr;
+    break;
   }
 
   CXCursor C = {K, 0, {Parent, S, TU}};

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to