[clang-tools-extra] [clang-tidy] Fix crash in readability-non-const-parameter with redecls (PR #200178)
Zeyi Xu via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 1 19:56:00 PDT 2026
https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/200178
>From e03ba2f0a7aaf3e0d94064e7e03879937f82c167 Mon Sep 17 00:00:00 2001
From: Zeyi Xu <mitchell.xu2 at gmail.com>
Date: Thu, 28 May 2026 21:33:59 +0800
Subject: [PATCH 1/2] [clang-tidy] Fix crash in readability-non-const-parameter
with redecls
---
.../clang-tidy/readability/NonConstParameterCheck.cpp | 7 ++++++-
clang-tools-extra/docs/ReleaseNotes.rst | 3 +++
.../checkers/readability/non-const-parameter.cpp | 8 ++++++++
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
index cc12479bcd86e..f3414aaa552f1 100644
--- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
@@ -104,7 +104,12 @@ void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) {
} else if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("Mark")) {
const QualType T = VD->getType();
if (T->isDependentType()) {
- const Expr *Init = VD->getInit()->IgnoreParenCasts();
+ // Initializer matched by hasInitializer() may be attached to a different
+ // redeclaration.
+ const Expr *Init = VD->getInit();
+ if (!Init)
+ return;
+ Init = Init->IgnoreParenCasts();
if (const auto *U = dyn_cast<UnaryOperator>(Init);
U && U->getOpcode() == UO_Deref) {
markCanNotBeConst(U->getSubExpr(), true);
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 0b3bb091307e7..9c846377d797a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -715,6 +715,9 @@ Changes in existing checks
- Fixed a false positive in array subscript expressions where the types are
not yet resolved.
+ - Fixed a crash when analyzing a redeclaration whose initializer is attached
+ to another declaration.
+
- Improved :doc:`readability-redundant-casting
<clang-tidy/checks/readability/redundant-casting>` check by adding the
`IgnoreImplicitCasts` option (default `false`) to flag casts as redundant
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
index d3749285df071..1a56db3a10263 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
@@ -433,3 +433,11 @@ void dependentInitInGenericLambdaMultiArg() {
DependentCtor2<T> s(p, p);
};
}
+
+template <class T>
+struct StaticMemberWithDependentType {
+ static const T X = 0;
+};
+
+template <class T>
+const T StaticMemberWithDependentType<T>::X;
>From 18bb82a614ca9d2ea0b5e83eb6d7e6b950130357 Mon Sep 17 00:00:00 2001
From: Zeyi Xu <mitchell.xu2 at gmail.com>
Date: Tue, 2 Jun 2026 10:55:30 +0800
Subject: [PATCH 2/2] ~~
---
.../readability/NonConstParameterCheck.cpp | 18 +++++++++++-------
.../readability/non-const-parameter.cpp | 12 ++++++++++--
2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
index f3414aaa552f1..fa9184a290273 100644
--- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
@@ -14,6 +14,15 @@ using namespace clang::ast_matchers;
namespace clang::tidy::readability {
+namespace {
+AST_MATCHER_P(VarDecl, hasOwnInitializer, ast_matchers::internal::Matcher<Expr>,
+ InnerMatcher) {
+ const Expr *Initializer = Node.getInit();
+ return Initializer != nullptr &&
+ InnerMatcher.matches(*Initializer, Finder, Builder);
+}
+} // namespace
+
void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) {
// Add parameters to Parameters.
Finder->addMatcher(parmVarDecl().bind("Parm"), this);
@@ -32,7 +41,7 @@ void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) {
cxxUnresolvedConstructExpr()))
.bind("Mark"),
this);
- Finder->addMatcher(varDecl(hasInitializer(anything())).bind("Mark"), this);
+ Finder->addMatcher(varDecl(hasOwnInitializer(anything())).bind("Mark"), this);
}
void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) {
@@ -104,12 +113,7 @@ void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) {
} else if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("Mark")) {
const QualType T = VD->getType();
if (T->isDependentType()) {
- // Initializer matched by hasInitializer() may be attached to a different
- // redeclaration.
- const Expr *Init = VD->getInit();
- if (!Init)
- return;
- Init = Init->IgnoreParenCasts();
+ const Expr *Init = VD->getInit()->IgnoreParenCasts();
if (const auto *U = dyn_cast<UnaryOperator>(Init);
U && U->getOpcode() == UO_Deref) {
markCanNotBeConst(U->getSubExpr(), true);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
index 1a56db3a10263..b4918df347e5c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
@@ -435,9 +435,17 @@ void dependentInitInGenericLambdaMultiArg() {
}
template <class T>
-struct StaticMemberWithDependentType {
+struct StaticDepInClassInit {
static const T X = 0;
};
template <class T>
-const T StaticMemberWithDependentType<T>::X;
+const T StaticDepInClassInit<T>::X;
+
+template <class T>
+struct StaticDepOutOfClassInit {
+ static const T X;
+};
+
+template <class T>
+const T StaticDepOutOfClassInit<T>::X = 0;
More information about the cfe-commits
mailing list