[clang-tools-extra] [clang-tidy] Fix false positives for dependent initializers (PR #186953)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 18 21:26:54 PDT 2026
https://github.com/frank-suwen updated https://github.com/llvm/llvm-project/pull/186953
>From a8e66cd4b644c3277422458b750c701c3e72afd2 Mon Sep 17 00:00:00 2001
From: frank-suwen <suwenw2 at outlook.com>
Date: Mon, 16 Mar 2026 21:49:40 -0700
Subject: [PATCH 1/3] [clang-tidy] Fix false positives for dependent
initializers
Handle dependent initializers more conservatively in readability-non-const-parameter so generic lambda cases such as `T x(*p)` and dependent constructor calls do not trigger incorrect "pointer parameter can be pointer to const" warnings. Add a regression test for a dependent constructor call in a generic lambda.
---
.../readability/NonConstParameterCheck.cpp | 24 +++++++++++++++----
.../readability/non-const-parameter.cpp | 14 +++++++++++
2 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
index 9950eca3fa7bd..aeaf23fdfe52c 100644
--- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
@@ -103,10 +103,26 @@ 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())
- markCanNotBeConst(VD->getInit(), false);
- else if ((T->isPointerType() && !T->getPointeeType().isConstQualified()) ||
- T->isArrayType() || T->isRecordType())
+ if (T->isDependentType()) {
+ const Expr *Init = VD->getInit()->IgnoreParenCasts();
+ if (const auto *U = dyn_cast<UnaryOperator>(Init);
+ U && U->getOpcode() == UO_Deref) {
+ markCanNotBeConst(U->getSubExpr(), true);
+ } else if (const auto *PLE = dyn_cast<ParenListExpr>(Init)) {
+ for (unsigned I = 0; I < PLE->getNumExprs(); ++I) {
+ const Expr *E = PLE->getExpr(I)->IgnoreParenCasts();
+ if (const auto *U = dyn_cast<UnaryOperator>(E);
+ U && U->getOpcode() == UO_Deref)
+ markCanNotBeConst(U->getSubExpr(), true);
+ else
+ markCanNotBeConst(E, true);
+ }
+ } else {
+ markCanNotBeConst(Init, true);
+ }
+ } else if ((T->isPointerType() &&
+ !T->getPointeeType().isConstQualified()) ||
+ T->isArrayType() || T->isRecordType())
markCanNotBeConst(VD->getInit(), true);
else if (T->isLValueReferenceType() &&
!T->getPointeeType().isConstQualified())
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 c07312f989cea..fc53a95cb03b0 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
@@ -372,3 +372,17 @@ void testGenericLambdaIssue177354() {
T x(*p);
};
}
+
+template <typename T>
+struct DependentCtor {
+ DependentCtor(int *p);
+};
+
+void dependentInitInGenericLambda() {
+ auto lambda = []<typename T>(int *p) {
+ DependentCtor<T> s(p);
+ };
+
+ int x = 0;
+ lambda.operator()<int>(&x);
+}
>From c26097ce2435825521032651223111c6ea43004a Mon Sep 17 00:00:00 2001
From: frank-suwen <suwenw2 at outlook.com>
Date: Tue, 17 Mar 2026 22:34:31 -0700
Subject: [PATCH 2/3] [clang-tidy] Address lint feedback (add missing braces)
---
.../clang-tidy/readability/NonConstParameterCheck.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
index aeaf23fdfe52c..904b7dedb7496 100644
--- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
@@ -122,10 +122,10 @@ void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) {
}
} else if ((T->isPointerType() &&
!T->getPointeeType().isConstQualified()) ||
- T->isArrayType() || T->isRecordType())
+ T->isArrayType() || T->isRecordType()) {
markCanNotBeConst(VD->getInit(), true);
- else if (T->isLValueReferenceType() &&
- !T->getPointeeType().isConstQualified())
+ } else if (T->isLValueReferenceType() &&
+ !T->getPointeeType().isConstQualified())
markCanNotBeConst(VD->getInit(), false);
}
}
>From 7d9e59bf61331de24be6ce7a7a2d7e8382ef2fee Mon Sep 17 00:00:00 2001
From: frank-suwen <suwenw2 at outlook.com>
Date: Wed, 18 Mar 2026 21:22:42 -0700
Subject: [PATCH 3/3] [clang-tidy] Address lint feedback (add missing braces)
---
.../clang-tidy/readability/NonConstParameterCheck.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
index 904b7dedb7496..e983ed9d48f63 100644
--- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
@@ -125,8 +125,9 @@ void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) {
T->isArrayType() || T->isRecordType()) {
markCanNotBeConst(VD->getInit(), true);
} else if (T->isLValueReferenceType() &&
- !T->getPointeeType().isConstQualified())
+ !T->getPointeeType().isConstQualified()) {
markCanNotBeConst(VD->getInit(), false);
+ }
}
}
More information about the cfe-commits
mailing list