Author: Oleksandr Tarasiuk Date: 2026-02-13T17:09:45+02:00 New Revision: 5e706e1b4ba428fa21cbd51f1e41e01ade2310a7
URL: https://github.com/llvm/llvm-project/commit/5e706e1b4ba428fa21cbd51f1e41e01ade2310a7 DIFF: https://github.com/llvm/llvm-project/commit/5e706e1b4ba428fa21cbd51f1e41e01ade2310a7.diff LOG: [Clang] enhance loop analysis to handle variable changes inside lambdas (#135573) Fixes #132038 --- This PR extends `-Wloop-analysis` to handle variable modifications inside lambda expressions. Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaStmt.cpp clang/test/SemaCXX/warn-loop-analysis.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 110761081e796..4f732ba81d78f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -239,6 +239,9 @@ Improvements to Clang's diagnostics - Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and made sure that only one such diagnostic and FixIt is emitted per declaration group. (#GH179354) +- The ``-Wloop-analysis`` warning has been extended to catch more cases of + variable modification inside lambda expressions (#GH132038). + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index ba5ba80d6a0bc..b74af55d1bea1 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -1996,9 +1996,33 @@ namespace { } void VisitDeclRefExpr(DeclRefExpr *E) { - if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) + if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) { if (Decls.count(VD)) FoundDecl = true; + } else if (const auto *MD = dyn_cast<CXXMethodDecl>(E->getDecl()); + MD && isLambdaCallOperator(MD)) { + // FIXME: This has limitations handling updates to the loop control + // variable that occur indirectly inside a lambda called from the loop + // body. For example: + // + // int a = 0; + // int *c = &a; + // auto incr_c = [c]() { ++*c; }; + // for (a = 10; a <= 20; incr_c()) + // foo(a); + for (const auto &Capture : MD->getParent()->captures()) { + if (!Capture.capturesVariable()) + continue; + + LambdaCaptureKind CK = Capture.getCaptureKind(); + if (CK != LCK_ByRef) + continue; + + const auto *VD = dyn_cast<VarDecl>(Capture.getCapturedVar()); + if (VD && Decls.count(VD)) + FoundDecl = true; + } + } } void VisitPseudoObjectExpr(PseudoObjectExpr *POE) { diff --git a/clang/test/SemaCXX/warn-loop-analysis.cpp b/clang/test/SemaCXX/warn-loop-analysis.cpp index 324dd386292ac..7773bef0cd238 100644 --- a/clang/test/SemaCXX/warn-loop-analysis.cpp +++ b/clang/test/SemaCXX/warn-loop-analysis.cpp @@ -299,3 +299,45 @@ void test10() { for (auto[i, j, k] = arr; i < a; ++i) { } for (auto[i, j, k] = arr; i < a; ++arr[0]) { } }; + +namespace GH132038 { +extern void foo(int); +void test1() { + int a = 0; + auto incr_a = [&a]() { ++a; }; + + for (int b = 10; a <= b; incr_a()) + foo(a); + + for (int b = 10; a <= b;) + incr_a(); + + for (int b = 10; a <= b; [&a]() { ++a; }()) { } + for (int b = 10; a <= b; [&a]() { }()) { } +} + +void test2() { + int a = 0; + int *c = &a; + + auto incr_a = [a]() { }; + auto incr_b = [](int b) { }; + auto incr_c = [c]() { ++*c; }; + + for (int b = 10; a <= b; incr_a()) // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}} + foo(a); + + for (int b = 10; a <= b;) // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}} + incr_a(); + + for (int b = 10; a <= b; incr_b(b)) // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}} + foo(a); + + for (int b = 10; a <= b;) // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}} + incr_b(b); + + // FIXME: handle modification of loop control variable inside lambda body + for (a = 10; a <= 20; incr_c()) // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + foo(a); +} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
