@@ -250,6 +250,10 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExp
250250 unsigned &msg,
251251 CastKind &Kind,
252252 CXXCastPath &BasePath);
253+ static TryCastResult TryStaticMemberFunctionPointerToFunctionPointerCast (
254+ Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestType,
255+ bool CStyle, SourceRange OpRange, unsigned &msg, CastKind &Kind,
256+ CXXCastPath &BasePath);
253257
254258static TryCastResult
255259TryStaticImplicitCast (Sema &Self, ExprResult &SrcExpr, QualType DestType,
@@ -1430,6 +1434,13 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
14301434 }
14311435 }
14321436
1437+ // GCC extension: convert a PMF constant into a function pointer.
1438+ tcr = TryStaticMemberFunctionPointerToFunctionPointerCast (
1439+ Self, SrcExpr, SrcType, DestType, CStyle, OpRange, msg, Kind, BasePath);
1440+
1441+ if (tcr != TC_NotApplicable)
1442+ return tcr;
1443+
14331444 // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast.
14341445 // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance.
14351446 tcr = TryStaticPointerDowncast (Self, SrcType, DestType, CStyle, OpRange, msg,
@@ -1834,6 +1845,59 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
18341845 return TC_Success;
18351846}
18361847
1848+ // / TryStaticMemberFunctionPointerToFunctionPointerCast - Tests whether a
1849+ // / conversion from PMF constant to function pointer is valid.
1850+ TryCastResult TryStaticMemberFunctionPointerToFunctionPointerCast (
1851+ Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestType,
1852+ bool CStyle, SourceRange OpRange, unsigned &msg, CastKind &Kind,
1853+ CXXCastPath &BasePath) {
1854+ const TargetCXXABI &CXXABI = Self.Context .getTargetInfo ().getCXXABI ();
1855+ if (!CXXABI.isItaniumFamily ())
1856+ return TC_NotApplicable;
1857+
1858+ const PointerType *DestPtr = DestType->getAs <PointerType>();
1859+ if (!DestPtr)
1860+ return TC_NotApplicable;
1861+
1862+ const FunctionProtoType *DestFnType =
1863+ DestPtr->getPointeeType ()->getAs <FunctionProtoType>();
1864+ if (!DestFnType || DestFnType->getNumParams () == 0 )
1865+ return TC_NotApplicable;
1866+
1867+ auto *ClsPtr = DestFnType->getParamType (0 )->getAs <PointerType>();
1868+ if (!ClsPtr)
1869+ return TC_NotApplicable;
1870+
1871+ auto *ClsRec = ClsPtr->getPointeeType ()->getAs <RecordType>();
1872+ if (!ClsRec)
1873+ return TC_NotApplicable;
1874+
1875+ auto *ClsTy = ClsRec->getAsCXXRecordDecl ();
1876+ if (!ClsTy)
1877+ return TC_NotApplicable;
1878+
1879+ auto EPI = DestFnType->getExtProtoInfo ();
1880+ EPI.TypeQuals = ClsPtr->getPointeeType ().getQualifiers ();
1881+ auto FuncTy =
1882+ Self.Context .getFunctionType (DestFnType->getCallResultType (Self.Context ),
1883+ DestFnType->param_types ().drop_front (), EPI);
1884+ auto DestPMFTy = Self.Context .getMemberPointerType (FuncTy, nullptr , ClsTy);
1885+
1886+ ExprResult Result = SrcExpr;
1887+
1888+ if (SrcType.getCanonicalType () != DestPMFTy) {
1889+ TryCastResult Res = TryStaticMemberPointerUpcast (
1890+ Self, Result, SrcType, DestType, CStyle, OpRange, msg, Kind, BasePath);
1891+ if (Res == TC_NotApplicable)
1892+ return TC_NotApplicable;
1893+ }
1894+
1895+ DestPMFTy->dump ();
1896+
1897+ // SrcExpr = Result;
1898+ return TC_NotApplicable;
1899+ }
1900+
18371901// / TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2
18381902// / is valid:
18391903// /
0 commit comments