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

Reply via email to