[clang] [clang-tools-extra] [NFC] Add implicit cast kinds for function pointer conversions (PR #110048)

via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 25 18:36:05 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Akira Hatanaka (ahatanak)

<details>
<summary>Changes</summary>

The new cast kinds are needed to distinguish between no-op conversions and conversions from pointers to noexcept functions to pointers to functions without noexcept as the latter can cause function pointers to be re-signed on arm64e.

See https://github.com/llvm/llvm-project/pull/109056 for background.

---

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


40 Files Affected:

- (modified) clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp (+2) 
- (modified) clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp (+3-1) 
- (modified) clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp (+6-1) 
- (modified) clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp (+3-1) 
- (modified) clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp (+3-1) 
- (modified) clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp (+7-2) 
- (modified) clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp (+2) 
- (modified) clang-tools-extra/clangd/Hover.cpp (+2) 
- (modified) clang/include/clang/AST/IgnoreExpr.h (+3-1) 
- (modified) clang/include/clang/AST/OperationKinds.def (+8) 
- (modified) clang/lib/ARCMigrate/TransBlockObjCVariable.cpp (+4-2) 
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+4) 
- (modified) clang/lib/AST/Expr.cpp (+23-5) 
- (modified) clang/lib/AST/ExprCXX.cpp (+5-1) 
- (modified) clang/lib/AST/ExprConstant.cpp (+14-3) 
- (modified) clang/lib/Analysis/CFG.cpp (+2) 
- (modified) clang/lib/Analysis/ExprMutationAnalyzer.cpp (+7-5) 
- (modified) clang/lib/Analysis/FlowSensitive/Transfer.cpp (+6-2) 
- (modified) clang/lib/Analysis/ThreadSafety.cpp (+3-1) 
- (modified) clang/lib/Analysis/ThreadSafetyCommon.cpp (+2) 
- (modified) clang/lib/CodeGen/CGDecl.cpp (+2) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+5-1) 
- (modified) clang/lib/CodeGen/CGExprAgg.cpp (+4) 
- (modified) clang/lib/CodeGen/CGExprComplex.cpp (+2) 
- (modified) clang/lib/CodeGen/CGExprConstant.cpp (+2) 
- (modified) clang/lib/CodeGen/CGExprScalar.cpp (+3-1) 
- (modified) clang/lib/Edit/RewriteObjCFoundationAPI.cpp (+2) 
- (modified) clang/lib/Sema/CheckExprLifetime.cpp (+2) 
- (modified) clang/lib/Sema/SemaChecking.cpp (+4) 
- (modified) clang/lib/Sema/SemaDecl.cpp (+3-1) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+3-1) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+2) 
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+5-1) 
- (modified) clang/lib/Sema/SemaInit.cpp (+2-2) 
- (modified) clang/lib/Sema/SemaOverload.cpp (+5-1) 
- (modified) clang/lib/Sema/SemaStmt.cpp (+2) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp (+2) 
- (modified) clang/lib/StaticAnalyzer/Core/SValBuilder.cpp (+2) 
- (added) clang/test/AST/ast-dump-function-pointer-conversion.cpp (+30) 
- (modified) clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4-ast.cpp (+2-2) 


``````````diff
diff --git a/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp
index 8989444dde1300..acb7112fa2abed 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp
@@ -27,6 +27,8 @@ void SwappedArgumentsCheck::registerMatchers(MatchFinder *Finder) {
 static const Expr *ignoreNoOpCasts(const Expr *E) {
   if (auto *Cast = dyn_cast<CastExpr>(E))
     if (Cast->getCastKind() == CK_LValueToRValue ||
+        Cast->getCastKind() == CK_FunctionPointerConversion ||
+        Cast->getCastKind() == CK_MemberFunctionPointerConversion ||
         Cast->getCastKind() == CK_NoOp)
       return ignoreNoOpCasts(Cast->getSubExpr());
   return E;
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
index 5e255dcaacd262..bab08496e90e86 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
@@ -90,7 +90,9 @@ void ProTypeCstyleCastCheck::check(const MatchFinder::MatchResult &Result) {
     return;
   }
 
-  if (MatchedCast->getCastKind() == CK_NoOp &&
+  if ((MatchedCast->getCastKind() == CK_NoOp ||
+       MatchedCast->getCastKind() == CK_FunctionPointerConversion ||
+       MatchedCast->getCastKind() == CK_MemberFunctionPointerConversion) &&
       needsConstCast(SourceType, MatchedCast->getType())) {
     diag(MatchedCast->getBeginLoc(),
          "do not use C-style cast to cast away constness");
diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
index 3109bbb3724c79..888f7b122b82c3 100644
--- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
@@ -123,7 +123,10 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
       DestTypeAsWritten->isRecordType() &&
       !DestTypeAsWritten->isElaboratedTypeSpecifier();
 
-  if (CastExpr->getCastKind() == CK_NoOp && !FnToFnCast) {
+  if ((CastExpr->getCastKind() == CK_NoOp ||
+       CastExpr->getCastKind() == CK_FunctionPointerConversion ||
+       CastExpr->getCastKind() == CK_MemberFunctionPointerConversion) &&
+      !FnToFnCast) {
     // Function pointer/reference casts may be needed to resolve ambiguities in
     // case of overloaded functions, so detection of redundant casts is trickier
     // in this case. Don't emit "redundant cast" warnings for function
@@ -201,6 +204,8 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
     }
     return;
   case CK_NoOp:
+  case CK_FunctionPointerConversion:
+  case CK_MemberFunctionPointerConversion:
     if (FnToFnCast) {
       ReplaceWithNamedCast("static_cast");
       return;
diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
index 1c6a1618ebbc4f..801d97ef2988ba 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -500,7 +500,9 @@ static bool canBeModified(ASTContext *Context, const Expr *E) {
   if (Parents.size() != 1)
     return true;
   if (const auto *Cast = Parents[0].get<ImplicitCastExpr>()) {
-    if ((Cast->getCastKind() == CK_NoOp &&
+    if (((Cast->getCastKind() == CK_NoOp ||
+          Cast->getCastKind() == CK_FunctionPointerConversion ||
+          Cast->getCastKind() == CK_MemberFunctionPointerConversion) &&
          Context->hasSameType(Cast->getType(), E->getType().withConst())) ||
         (Cast->getCastKind() == CK_LValueToRValue &&
          !Cast->getType().isNull() && Cast->getType()->isFundamentalType()))
diff --git a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
index 86fca0722dcd82..4fc32e1d1572eb 100644
--- a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
@@ -24,7 +24,9 @@ namespace clang::tidy::performance {
 // case we skip the first cast expr.
 static bool isNonTrivialImplicitCast(const Stmt *ST) {
   if (const auto *ICE = dyn_cast<ImplicitCastExpr>(ST)) {
-    return (ICE->getCastKind() != CK_NoOp) ||
+    return (ICE->getCastKind() != CK_NoOp &&
+            ICE->getCastKind() != CK_FunctionPointerConversion &&
+            ICE->getCastKind() != CK_MemberFunctionPointerConversion) ||
            isNonTrivialImplicitCast(ICE->getSubExpr());
   }
   return false;
diff --git a/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp
index d42fcba70e81b4..751cd637a02334 100644
--- a/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp
@@ -97,7 +97,9 @@ class FindUsageOfThis : public RecursiveASTVisitor<FindUsageOfThis> {
   //  (possibly `-UnaryOperator Deref)
   //        `-CXXThisExpr 'S *' this
   bool visitUser(const ImplicitCastExpr *Cast) {
-    if (Cast->getCastKind() != CK_NoOp)
+    if (Cast->getCastKind() != CK_NoOp &&
+        Cast->getCastKind() != CK_FunctionPointerConversion &&
+        Cast->getCastKind() != CK_MemberFunctionPointerConversion)
       return false; // Stop traversal.
 
     // Only allow NoOp cast to 'const S' or 'const S *'.
@@ -159,7 +161,10 @@ class FindUsageOfThis : public RecursiveASTVisitor<FindUsageOfThis> {
       if (Cast->getCastKind() == CK_LValueToRValue)
         return true;
 
-      if (Cast->getCastKind() == CK_NoOp && Cast->getType().isConstQualified())
+      if ((Cast->getCastKind() == CK_NoOp ||
+           Cast->getCastKind() == CK_FunctionPointerConversion ||
+           Cast->getCastKind() == CK_MemberFunctionPointerConversion) &&
+          Cast->getType().isConstQualified())
         return true;
     }
 
diff --git a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
index 106feb7fb41720..87e523eaaa7718 100644
--- a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
+++ b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
@@ -240,6 +240,8 @@ AST_MATCHER_P(DeclRefExpr, doesNotMutateObject, int, Indirections) {
         case CK_BaseToDerived:
         case CK_DerivedToBase:
         case CK_UncheckedDerivedToBase:
+        case CK_FunctionPointerConversion:
+        case CK_MemberFunctionPointerConversion:
         case CK_Dynamic:
         case CK_BaseToDerivedMemberPointer:
         case CK_DerivedToBaseMemberPointer:
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 298fa79e3fd0ba..5cb2ecd1d55726 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -1118,6 +1118,8 @@ void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
     if (const auto *ImplicitCast = CastNode->ASTNode.get<ImplicitCastExpr>()) {
       switch (ImplicitCast->getCastKind()) {
       case CK_NoOp:
+      case CK_FunctionPointerConversion:
+      case CK_MemberFunctionPointerConversion:
       case CK_DerivedToBase:
       case CK_UncheckedDerivedToBase:
         // If it was a reference before, it's still a reference.
diff --git a/clang/include/clang/AST/IgnoreExpr.h b/clang/include/clang/AST/IgnoreExpr.h
index 917bada61fa6fd..967c381dfa9dc5 100644
--- a/clang/include/clang/AST/IgnoreExpr.h
+++ b/clang/include/clang/AST/IgnoreExpr.h
@@ -102,7 +102,9 @@ inline Expr *IgnoreBaseCastsSingleStep(Expr *E) {
   if (auto *CE = dyn_cast<CastExpr>(E))
     if (CE->getCastKind() == CK_DerivedToBase ||
         CE->getCastKind() == CK_UncheckedDerivedToBase ||
-        CE->getCastKind() == CK_NoOp)
+        CE->getCastKind() == CK_NoOp ||
+        CE->getCastKind() == CK_FunctionPointerConversion ||
+        CE->getCastKind() == CK_MemberFunctionPointerConversion)
       return CE->getSubExpr();
 
   return E;
diff --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def
index 8788b8ff0ef0a4..25cd0dbb5e3a3b 100644
--- a/clang/include/clang/AST/OperationKinds.def
+++ b/clang/include/clang/AST/OperationKinds.def
@@ -84,6 +84,14 @@ CAST_OPERATION(LValueToRValue)
 ///   void () noexcept -> void ()
 CAST_OPERATION(NoOp)
 
+/// CK_FunctionPointerConversion - A conversion from pointer/reference to
+/// noexcept function to pointer/reference to function.
+CAST_OPERATION(FunctionPointerConversion)
+
+/// CK_MemberFunctionPointerConversion - A conversion from pointer to noexcept
+/// member function to pointer to member function.
+CAST_OPERATION(MemberFunctionPointerConversion)
+
 /// CK_BaseToDerived - A conversion from a C++ class pointer/reference
 /// to a derived class pointer/reference.
 ///   B *b = static_cast<B*>(a);
diff --git a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
index 1e4db33135b6a1..7295f064849ea6 100644
--- a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
+++ b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
@@ -53,8 +53,10 @@ class RootBlockObjCVarRewriter :
         if (ref->getDecl() == Var) {
           if (castE->getCastKind() == CK_LValueToRValue)
             return true; // Using the value of the variable.
-          if (castE->getCastKind() == CK_NoOp && castE->isLValue() &&
-              Var->getASTContext().getLangOpts().CPlusPlus)
+          if ((castE->getCastKind() == CK_NoOp ||
+               castE->getCastKind() == CK_FunctionPointerConversion ||
+               castE->getCastKind() == CK_MemberFunctionPointerConversion) &&
+              castE->isLValue() && Var->getASTContext().getLangOpts().CPlusPlus)
             return true; // Binding to const C++ reference.
         }
       }
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index e54b6568d7060b..7d448d0e1cbeb2 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -429,6 +429,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
   case CK_FunctionToPointerDecay:
   case CK_NonAtomicToAtomic:
   case CK_NoOp:
+  case CK_FunctionPointerConversion:
+  case CK_MemberFunctionPointerConversion:
   case CK_UserDefinedConversion:
   case CK_AddressSpaceConversion:
   case CK_CPointerToObjCPointerCast:
@@ -3161,6 +3163,8 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
     for (; auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped);
          Stripped = ICE->getSubExpr())
       if (ICE->getCastKind() != CK_NoOp &&
+          ICE->getCastKind() != CK_FunctionPointerConversion &&
+          ICE->getCastKind() != CK_MemberFunctionPointerConversion &&
           ICE->getCastKind() != CK_IntegralCast)
         break;
 
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 2e463fc00c6b68..c62ffa9bf7df59 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -98,7 +98,9 @@ const Expr *Expr::skipRValueSubobjectAdjustments(
         continue;
       }
 
-      if (CE->getCastKind() == CK_NoOp) {
+      if (CE->getCastKind() == CK_NoOp ||
+          CE->getCastKind() == CK_FunctionPointerConversion ||
+          CE->getCastKind() == CK_MemberFunctionPointerConversion) {
         E = CE->getSubExpr();
         continue;
       }
@@ -1926,6 +1928,8 @@ bool CastExpr::CastConsistency() const {
   case CK_Dependent:
   case CK_LValueToRValue:
   case CK_NoOp:
+  case CK_FunctionPointerConversion:
+  case CK_MemberFunctionPointerConversion:
   case CK_AtomicToNonAtomic:
   case CK_NonAtomicToAtomic:
   case CK_PointerToBoolean:
@@ -3188,7 +3192,9 @@ static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
     E = M->getSubExpr();
 
   while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
-    if (ICE->getCastKind() == CK_NoOp)
+    if (ICE->getCastKind() == CK_NoOp ||
+        ICE->getCastKind() == CK_FunctionPointerConversion ||
+        ICE->getCastKind() == CK_MemberFunctionPointerConversion)
       E = ICE->getSubExpr();
     else
       break;
@@ -3198,7 +3204,9 @@ static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
     E = BE->getSubExpr();
 
   while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
-    if (ICE->getCastKind() == CK_NoOp)
+    if (ICE->getCastKind() == CK_NoOp ||
+        ICE->getCastKind() == CK_FunctionPointerConversion ||
+        ICE->getCastKind() == CK_MemberFunctionPointerConversion)
       E = ICE->getSubExpr();
     else
       break;
@@ -3263,6 +3271,8 @@ bool Expr::isImplicitCXXThis() const {
 
     if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
       if (ICE->getCastKind() == CK_NoOp ||
+          ICE->getCastKind() == CK_FunctionPointerConversion ||
+          ICE->getCastKind() == CK_MemberFunctionPointerConversion ||
           ICE->getCastKind() == CK_LValueToRValue ||
           ICE->getCastKind() == CK_DerivedToBase ||
           ICE->getCastKind() == CK_UncheckedDerivedToBase) {
@@ -3478,6 +3488,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
 
     // Handle misc casts we want to ignore.
     if (CE->getCastKind() == CK_NoOp ||
+        CE->getCastKind() == CK_FunctionPointerConversion ||
+        CE->getCastKind() == CK_MemberFunctionPointerConversion ||
         CE->getCastKind() == CK_LValueToRValue ||
         CE->getCastKind() == CK_ToUnion ||
         CE->getCastKind() == CK_ConstructorConversion ||
@@ -4113,7 +4125,10 @@ FieldDecl *Expr::getSourceBitField() {
 
   while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
     if (ICE->getCastKind() == CK_LValueToRValue ||
-        (ICE->isGLValue() && ICE->getCastKind() == CK_NoOp))
+        (ICE->isGLValue() &&
+         (ICE->getCastKind() == CK_NoOp ||
+          ICE->getCastKind() == CK_FunctionPointerConversion ||
+          ICE->getCastKind() == CK_MemberFunctionPointerConversion)))
       E = ICE->getSubExpr()->IgnoreParens();
     else
       break;
@@ -4167,7 +4182,10 @@ bool Expr::refersToVectorElement() const {
   const Expr *E = this->IgnoreParens();
 
   while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
-    if (ICE->isGLValue() && ICE->getCastKind() == CK_NoOp)
+    if (ICE->isGLValue() &&
+        (ICE->getCastKind() == CK_NoOp ||
+         ICE->getCastKind() == CK_FunctionPointerConversion ||
+         ICE->getCastKind() == CK_MemberFunctionPointerConversion))
       E = ICE->getSubExpr()->IgnoreParens();
     else
       break;
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 83ce404add5f50..a3f09786960b1f 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -344,8 +344,12 @@ QualType CXXDeleteExpr::getDestroyedType() const {
   while (const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
     if (ICE->getCastKind() == CK_DerivedToBase ||
         ICE->getCastKind() == CK_UncheckedDerivedToBase ||
-        ICE->getCastKind() == CK_NoOp) {
+        ICE->getCastKind() == CK_NoOp ||
+        ICE->getCastKind() == CK_FunctionPointerConversion ||
+        ICE->getCastKind() == CK_MemberFunctionPointerConversion) {
       assert((ICE->getCastKind() == CK_NoOp ||
+              ICE->getCastKind() == CK_FunctionPointerConversion ||
+              ICE->getCastKind() == CK_MemberFunctionPointerConversion ||
               getOperatorDelete()->isDestroyingOperatorDelete()) &&
              "only a destroying operator delete can have a converted arg");
       Arg = ICE->getSubExpr();
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6387e375dda79c..28f829e612be47 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6247,7 +6247,9 @@ static bool MaybeHandleUnionActiveMemberChange(EvalInfo &Info,
     } else if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
       // Step over a derived-to-base conversion.
       E = ICE->getSubExpr();
-      if (ICE->getCastKind() == CK_NoOp)
+      if (ICE->getCastKind() == CK_NoOp ||
+          ICE->getCastKind() == CK_FunctionPointerConversion ||
+          ICE->getCastKind() == CK_MemberFunctionPointerConversion)
         continue;
       if (ICE->getCastKind() != CK_DerivedToBase &&
           ICE->getCastKind() != CK_UncheckedDerivedToBase)
@@ -8301,6 +8303,8 @@ class ExprEvaluatorBase
     }
 
     case CK_NoOp:
+    case CK_FunctionPointerConversion:
+    case CK_MemberFunctionPointerConversion:
     case CK_UserDefinedConversion:
       return StmtVisitorTy::Visit(E->getSubExpr());
 
@@ -10074,6 +10078,8 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
     for (; auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped);
          Stripped = ICE->getSubExpr())
       if (ICE->getCastKind() != CK_NoOp &&
+          ICE->getCastKind() != CK_FunctionPointerConversion &&
+          ICE->getCastKind() != CK_MemberFunctionPointerConversion &&
           ICE->getCastKind() != CK_IntegralCast)
         break;
 
@@ -12210,8 +12216,9 @@ static const Expr *ignorePointerCastsAndParens(const Expr *E) {
   // We only conservatively allow a few kinds of casts, because this code is
   // inherently a simple solution that seeks to support the common case.
   auto CastKind = Cast->getCastKind();
-  if (CastKind != CK_NoOp && CastKind != CK_BitCast &&
-      CastKind != CK_AddressSpaceConversion)
+  if (CastKind != CK_NoOp && CastKind != CK_FunctionPointerConversion &&
+      CastKind != CK_MemberFunctionPointerConversion &&
+      CastKind != CK_BitCast && CastKind != CK_AddressSpaceConversion)
     return NoParens;
 
   const auto *SubExpr = Cast->getSubExpr();
@@ -14448,6 +14455,8 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
   QualType SrcType = SubExpr->getType();
 
   switch (E->getCastKind()) {
+  case CK_FunctionPointerConversion:
+  case CK_MemberFunctionPointerConversion:
   case CK_BaseToDerived:
   case CK_DerivedToBase:
   case CK_UncheckedDerivedToBase:
@@ -15288,6 +15297,8 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
   case CK_BaseToDerived:
   case CK_DerivedToBase:
   case CK_UncheckedDerivedToBase:
+  case CK_FunctionPointerConversion:
+  case CK_MemberFunctionPointerConversion:
   case CK_Dynamic:
   case CK_ToUnion:
   case CK_ArrayToPointerDecay:
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index f678ac6f2ff36a..baa5f96f8cbdbe 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -1491,6 +1491,8 @@ void CFGBuilder::findConstructionContexts(
     // Should we support other implicit cast kinds?
     switch (Cast->getCastKind()) {
     case CK_NoOp:
+    case CK_FunctionPointerConversion:
+    case CK_MemberFunctionPointerConversion:
     case CK_ConstructorConversion:
       findConstructionContexts(Layer, Cast->getSubExpr());
       break;
diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp
index 6d726ae44104ed..8f19bd7e918706 100644
--- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp
+++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp
@@ -377,11 +377,13 @@ ExprMutationAnalyzer::Analyzer::findDirectMutation(const Expr *Exp) {
   // We're assuming 'Exp' is mutated as soon as its address is taken, though in
   // theory we can follow the pointer and see whether it escaped `Stm` or is
   // dereferenced and then mutated. This is left for future improvements.
-  const auto AsAmpersandOperand =
-      unaryOperator(hasOperatorName("&"),
-                    // A NoOp implicit cast is adding const.
-                    unless(hasParent(implicitCastExpr(hasCastKind(CK_NoOp)))),
-                    hasUnaryOperand(canResolveToExpr(Exp)));
+  const auto AsAmpersandOperand = unaryOperator(
+      hasOperatorName("&"),
+      // A NoOp implicit cast is adding const.
+      unless(hasParent(implicitCastExpr(
+          anyOf(hasCastKind(CK_NoOp), hasCastKind(CK_FunctionPointerConversion),
+                hasCastKind(CK_MemberFunctionPointerConversion))))),
+      hasUnaryOperand(canResolveToExpr(Exp)));
   const auto AsPo...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/110048


More information about the cfe-commits mailing list