llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangd 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits