https://github.com/frank-suwen updated https://github.com/llvm/llvm-project/pull/186953
>From 4f18e6e3636b78571f6711afbb998512f0e917d6 Mon Sep 17 00:00:00 2001 From: frank-suwen <[email protected]> Date: Mon, 16 Mar 2026 21:49:40 -0700 Subject: [PATCH 1/6] [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 | 12 ++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp index ae93d299f8774..5ed6ffa7ddfa9 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 eec29efb87bb0..ac914cdb0ce24 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 @@ -387,4 +387,16 @@ void useDependentArray() { double ToFill[2] = {}; dependentArray1(ToFill, 0, 1.0); dependentArray2(ToFill, 0, 1.0); +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 efd4fbfbb52157451dfd7a642e625e2419492dd2 Mon Sep 17 00:00:00 2001 From: frank-suwen <[email protected]> Date: Tue, 17 Mar 2026 22:34:31 -0700 Subject: [PATCH 2/6] [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 5ed6ffa7ddfa9..5940cfdb5d24f 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 8c57d9746124613d2f7d4ba32c2ea4718caaaaa2 Mon Sep 17 00:00:00 2001 From: frank-suwen <[email protected]> Date: Wed, 18 Mar 2026 21:22:42 -0700 Subject: [PATCH 3/6] [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 5940cfdb5d24f..0cfaa77cb8261 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); + } } } >From a36e9a0417c13d15c3eceea96762cfb1c2788f41 Mon Sep 17 00:00:00 2001 From: frank-suwen <[email protected]> Date: Thu, 19 Mar 2026 22:18:47 -0700 Subject: [PATCH 4/6] [clang-tidy] Update release notes for non-const-parameter fix --- clang-tools-extra/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index c464be5f6311a..961065528043f 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -582,7 +582,7 @@ Changes in existing checks <clang-tidy/checks/readability/non-const-parameter>` check: - Avoid false positives on parameters used in dependent expressions - (e.g. inside generic lambdas). + (e.g. inside generic lambdas), including constructor-style dependent initializers. - Fixed a false positive in array subscript expressions where the types are not yet resolved. >From a04a0abb58ddfd6fa2aa6959d5a7745bf76dd923 Mon Sep 17 00:00:00 2001 From: frank-suwen <[email protected]> Date: Wed, 25 Mar 2026 19:54:38 -0700 Subject: [PATCH 5/6] [clang-tidy] Add coverage for dependent initializer cases --- .../readability/non-const-parameter.cpp | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) 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 ac914cdb0ce24..18c41875dda5e 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 @@ -387,16 +387,47 @@ void useDependentArray() { double ToFill[2] = {}; dependentArray1(ToFill, 0, 1.0); dependentArray2(ToFill, 0, 1.0); +void testGenericLambdaIssue177354EqualsInit() { + // CHECK-MESSAGES-NOT: warning: pointer parameter 'p' can be pointer to const + auto genericLambda = []<typename T>(int *p) { + T x = *p; + }; +} + +void testGenericLambdaIssue177354Parens() { + // CHECK-MESSAGES-NOT: warning: pointer parameter 'p' can be pointer to const + auto genericLambda = []<typename T>(int *p) { + T x((*p)); + }; +} + template <typename T> struct DependentCtor { DependentCtor(int *p); }; +template <typename T> +struct DependentCtor2 { + DependentCtor2(int *p, int *q); +}; + void dependentInitInGenericLambda() { + // CHECK-MESSAGES-NOT: warning: pointer parameter 'p' can be pointer to const auto lambda = []<typename T>(int *p) { DependentCtor<T> s(p); }; +} - int x = 0; - lambda.operator()<int>(&x); +void dependentInitInGenericLambdaParens() { + // CHECK-MESSAGES-NOT: warning: pointer parameter 'p' can be pointer to const + auto lambda = []<typename T>(int *p) { + DependentCtor<T> s((p)); + }; +} + +void dependentInitInGenericLambdaMultiArg() { + // CHECK-MESSAGES-NOT: warning: pointer parameter 'p' can be pointer to const + auto lambda = []<typename T>(int *p) { + DependentCtor2<T> s(p, p); + }; } >From 65157cdcc5f53b691bc08213dfbf0ad2f97ce5e7 Mon Sep 17 00:00:00 2001 From: frank-suwen <[email protected]> Date: Tue, 12 May 2026 21:17:05 -0700 Subject: [PATCH 6/6] [clang-tidy] Use range-based for after rebase --- .../clang-tidy/readability/NonConstParameterCheck.cpp | 4 ++-- .../clang-tidy/checkers/readability/non-const-parameter.cpp | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp index 0cfaa77cb8261..cc12479bcd86e 100644 --- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp @@ -109,8 +109,8 @@ void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) { 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(); + for (const Expr *E : PLE->exprs()) { + E = E->IgnoreParenCasts(); if (const auto *U = dyn_cast<UnaryOperator>(E); 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 18c41875dda5e..d3749285df071 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 @@ -387,6 +387,8 @@ void useDependentArray() { double ToFill[2] = {}; dependentArray1(ToFill, 0, 1.0); dependentArray2(ToFill, 0, 1.0); +} + void testGenericLambdaIssue177354EqualsInit() { // CHECK-MESSAGES-NOT: warning: pointer parameter 'p' can be pointer to const auto genericLambda = []<typename T>(int *p) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
