[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