Author: Aditya Singh
Date: 2026-02-15T12:39:29+08:00
New Revision: 5548b24d18ad9e856bcb354a17b52c15fa37bf73

URL: 
https://github.com/llvm/llvm-project/commit/5548b24d18ad9e856bcb354a17b52c15fa37bf73
DIFF: 
https://github.com/llvm/llvm-project/commit/5548b24d18ad9e856bcb354a17b52c15fa37bf73.diff

LOG: [clang-tidy] Fix false positive for generic lambda parameters in 
readability-non-const-parameter (#179051)

Fixes #177354

### Summary
The `readability-non-const-parameter` check produces false positives on
generic lambda parameters, not fully resolved by #177345.

### Problem
Generic lambdas with explicit template parameters create dependent
contexts that cannot be analyzed at parse time:

```cpp
auto lambda = []<typename T>(int *p) {
  T x(*p);   // No longer warns
};
```

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
    clang-tools-extra/docs/ReleaseNotes.rst
    
clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp

Removed: 
    


################################################################################
diff  --git 
a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
index 2ecde56cd7af8..9950eca3fa7bd 100644
--- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
@@ -95,8 +95,7 @@ void NonConstParameterCheck::check(const 
MatchFinder::MatchResult &Result) {
         }
       }
     } else if (const auto *CE = dyn_cast<CXXUnresolvedConstructExpr>(S)) {
-      for (const auto *Arg : CE->arguments())
-        markCanNotBeConst(Arg->IgnoreParenCasts(), true);
+      markCanNotBeConst(CE, true);
     } else if (const auto *R = dyn_cast<ReturnStmt>(S)) {
       markCanNotBeConst(R->getRetValue(), true);
     } else if (const auto *U = dyn_cast<UnaryOperator>(S)) {
@@ -104,8 +103,10 @@ void NonConstParameterCheck::check(const 
MatchFinder::MatchResult &Result) {
     }
   } else if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("Mark")) {
     const QualType T = VD->getType();
-    if ((T->isPointerType() && !T->getPointeeType().isConstQualified()) ||
-        T->isArrayType() || T->isRecordType())
+    if (T->isDependentType())
+      markCanNotBeConst(VD->getInit(), false);
+    else if ((T->isPointerType() && !T->getPointeeType().isConstQualified()) ||
+             T->isArrayType() || T->isRecordType())
       markCanNotBeConst(VD->getInit(), true);
     else if (T->isLValueReferenceType() &&
              !T->getPointeeType().isConstQualified())
@@ -221,9 +222,17 @@ void NonConstParameterCheck::markCanNotBeConst(const Expr 
*E,
     for (const auto *Arg : Constr->arguments())
       if (const auto *M = dyn_cast<MaterializeTemporaryExpr>(Arg))
         markCanNotBeConst(cast<Expr>(M->getSubExpr()), CanNotBeConst);
+      else
+        markCanNotBeConst(Arg, CanNotBeConst);
+  } else if (const auto *CE = dyn_cast<CXXUnresolvedConstructExpr>(E)) {
+    for (const auto *Arg : CE->arguments())
+      markCanNotBeConst(Arg, CanNotBeConst);
   } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
     for (unsigned I = 0U; I < ILE->getNumInits(); ++I)
-      markCanNotBeConst(ILE->getInit(I), true);
+      markCanNotBeConst(ILE->getInit(I), CanNotBeConst);
+  } else if (const auto *PLE = dyn_cast<ParenListExpr>(E)) {
+    for (unsigned I = 0U; I < PLE->getNumExprs(); ++I)
+      markCanNotBeConst(PLE->getExpr(I), CanNotBeConst);
   } else if (CanNotBeConst) {
     // Referencing parameter.
     if (const auto *D = dyn_cast<DeclRefExpr>(E)) {

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 6799b2c136f38..0c487524390e3 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -229,7 +229,8 @@ Changes in existing checks
 
 - Improved :doc:`readability-non-const-parameter
   <clang-tidy/checks/readability/non-const-parameter>` check by avoiding false
-  positives on parameters used in dependent expressions.
+  positives on parameters used in dependent expressions (e.g. inside generic
+  lambdas).
 
 - Improved :doc:`readability-simplify-boolean-expr
   <clang-tidy/checks/readability/simplify-boolean-expr>` check to provide valid

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 0079fa9e96434..c07312f989cea 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
@@ -360,6 +360,15 @@ class B final {
 };
 
 void gh176623() {
+    // CHECK-MESSAGES-NOT: warning:
     auto const V1 = []<bool tc>(char* p) { auto X = A<tc>(p); };
+    // CHECK-MESSAGES-NOT: warning:
     auto const V2 = []<bool tc>(char* p) { auto Y = B(p); };
 }
+
+void testGenericLambdaIssue177354() {
+  // CHECK-MESSAGES-NOT: warning: pointer parameter 'p' can be pointer to const
+  auto genericLambda = []<typename T>(int *p) {
+    T x(*p);
+  };
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to