[clang] [clang-tools-extra] [clang] Make `IgnoreUnlessSpelledInSource` ignore `CallExpr`s more aggressively (PR #183882)
Victor Chernyakin via cfe-commits
cfe-commits at lists.llvm.org
Sat Mar 7 21:00:44 PST 2026
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/183882
>From 989c65f132a6bbe56f35b3cbd4bd36e036f9a1fc Mon Sep 17 00:00:00 2001
From: Victor Chernyakin <chernyakin.victor.j at outlook.com>
Date: Fri, 27 Feb 2026 21:43:59 -0800
Subject: [PATCH 1/2] [clang] Make `IgnoreUnlessSpelledInSource` ignore
`CallExpr`s more aggressively
---
.../readability/redundant-casting.cpp | 19 ++++++++++
clang/lib/AST/Expr.cpp | 24 +++----------
clang/unittests/AST/ASTTraverserTest.cpp | 36 +++++++++++++++++++
3 files changed, 59 insertions(+), 20 deletions(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp
index 3e723b8b61d1d..67b65d2e7f799 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp
@@ -13,6 +13,8 @@
// RUN: %check_clang_tidy -std=c++20 -check-suffix=,ALIASES %s readability-redundant-casting %t -- \
// RUN: -config='{CheckOptions: { readability-redundant-casting.IgnoreTypeAliases: true }}' \
// RUN: -- -fno-delayed-template-parsing -D CXX_20=1
+// RUN: %check_clang_tidy -std=c++23-or-later -check-suffix=,CXX23 %s readability-redundant-casting %t -- \
+// RUN: -- -fno-delayed-template-parsing
struct A {};
struct B : A {};
@@ -245,3 +247,20 @@ int g1() {
return fp();
}
} // namespace gh170476
+
+
+#if __cplusplus >= 202302L
+
+struct S {
+ operator int(this const S&);
+};
+
+void testCastingWithExplicitObjectParameterConversionOperator() {
+ int i = int(S {});
+
+ int j = int(S {}.operator int());
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:11: warning: redundant explicit casting to the same type 'int' as the sub-expression, remove this casting [readability-redundant-casting]
+ // CHECK-FIXES-CXX23: int j = S {}.operator int();
+}
+
+#endif // __cplusplus >= 202302L
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9632d88fae4e4..45daed276547d 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2550,18 +2550,6 @@ Stmt *BlockExpr::getBody() {
// Generic Expression Routines
//===----------------------------------------------------------------------===//
-/// Helper to determine wether \c E is a CXXConstructExpr constructing
-/// a DecompositionDecl. Used to skip Clang-generated calls to std::get
-/// for structured bindings.
-static bool IsDecompositionDeclRefExpr(const Expr *E) {
- const auto *Unwrapped = E->IgnoreUnlessSpelledInSource();
- const auto *Ref = dyn_cast<DeclRefExpr>(Unwrapped);
- if (!Ref)
- return false;
-
- return isa_and_nonnull<DecompositionDecl>(Ref->getDecl());
-}
-
bool Expr::isReadIfDiscardedInCPlusPlus11() const {
// In C++11, discarded-value expressions of a certain form are special,
// according to [expr]p10:
@@ -3178,10 +3166,11 @@ Expr *Expr::IgnoreUnlessSpelledInSource() {
};
// Used when Clang generates calls to std::get for decomposing
- // structured bindings.
+ // structured bindings or for implicit calls to member functions
+ // with explicit object parameters.
auto IgnoreImplicitCallSingleStep = [](Expr *E) {
auto *C = dyn_cast<CallExpr>(E);
- if (!C)
+ if (!C || isa<UserDefinedLiteral>(C))
return E;
// Looking for calls to a std::get, which usually just takes
@@ -3197,12 +3186,7 @@ Expr *Expr::IgnoreUnlessSpelledInSource() {
if (A->getSourceRange() != E->getSourceRange())
return E;
- // If the argument refers to a DecompositionDecl construction,
- // ignore it.
- if (IsDecompositionDeclRefExpr(A))
- return A;
-
- return E;
+ return A;
};
return IgnoreExprNodes(
diff --git a/clang/unittests/AST/ASTTraverserTest.cpp b/clang/unittests/AST/ASTTraverserTest.cpp
index bcbf01b6b0385..53b6096edb5ce 100644
--- a/clang/unittests/AST/ASTTraverserTest.cpp
+++ b/clang/unittests/AST/ASTTraverserTest.cpp
@@ -1659,6 +1659,42 @@ CallExpr
FN[0].getNodeAs<CallExpr>("decomp_call_with_default")),
R"cpp(
DeclRefExpr ''
+)cpp");
+ }
+
+ auto AST3 = buildASTFromCodeWithArgs(R"cpp(
+
+struct S {
+ operator int(this const S&);
+};
+
+void f() {
+ S s;
+ int i = int(s);
+}
+
+)cpp",
+ {"-std=c++23"});
+ {
+ auto FN = ast_matchers::match(
+ explicitCastExpr(hasSourceExpression(expr().bind("sourceExpr"))),
+ AST3->getASTContext());
+ EXPECT_EQ(FN.size(), 1u);
+
+ EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<Expr>("sourceExpr")),
+ R"cpp(
+ImplicitCastExpr
+`-CallExpr
+ |-ImplicitCastExpr
+ | `-DeclRefExpr 'operator int'
+ `-ImplicitCastExpr
+ `-DeclRefExpr 's'
+)cpp");
+
+ EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,
+ FN[0].getNodeAs<Expr>("sourceExpr")),
+ R"cpp(
+DeclRefExpr 's'
)cpp");
}
}
>From 901f05363a90023ea0145c01c1e6cbc741642c13 Mon Sep 17 00:00:00 2001
From: Victor Chernyakin <chernyakin.victor.j at outlook.com>
Date: Sat, 7 Mar 2026 21:00:09 -0800
Subject: [PATCH 2/2] Separate out clang-tidy test changes
---
.../readability/redundant-casting.cpp | 19 -------------------
1 file changed, 19 deletions(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp
index 67b65d2e7f799..3e723b8b61d1d 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp
@@ -13,8 +13,6 @@
// RUN: %check_clang_tidy -std=c++20 -check-suffix=,ALIASES %s readability-redundant-casting %t -- \
// RUN: -config='{CheckOptions: { readability-redundant-casting.IgnoreTypeAliases: true }}' \
// RUN: -- -fno-delayed-template-parsing -D CXX_20=1
-// RUN: %check_clang_tidy -std=c++23-or-later -check-suffix=,CXX23 %s readability-redundant-casting %t -- \
-// RUN: -- -fno-delayed-template-parsing
struct A {};
struct B : A {};
@@ -247,20 +245,3 @@ int g1() {
return fp();
}
} // namespace gh170476
-
-
-#if __cplusplus >= 202302L
-
-struct S {
- operator int(this const S&);
-};
-
-void testCastingWithExplicitObjectParameterConversionOperator() {
- int i = int(S {});
-
- int j = int(S {}.operator int());
- // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:11: warning: redundant explicit casting to the same type 'int' as the sub-expression, remove this casting [readability-redundant-casting]
- // CHECK-FIXES-CXX23: int j = S {}.operator int();
-}
-
-#endif // __cplusplus >= 202302L
More information about the cfe-commits
mailing list