Skip to content

Commit 93c8fc7

Browse files
committed
[Clang] enhance loop analysis to handle variable changes inside lambdas
1 parent 889dad7 commit 93c8fc7

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

clang/docs/ReleaseNotes.rst

+2
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,8 @@ Improvements to Clang's diagnostics
385385

386386
Fixes #GH131127
387387

388+
- The ``-Wloop-analysis`` warning now handles variable modifications inside lambda expressions (#GH132038).
389+
388390
Improvements to Clang's time-trace
389391
----------------------------------
390392

clang/lib/Sema/SemaStmt.cpp

+17-2
Original file line numberDiff line numberDiff line change
@@ -2002,9 +2002,24 @@ namespace {
20022002
}
20032003

20042004
void VisitDeclRefExpr(DeclRefExpr *E) {
2005-
if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
2005+
if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
20062006
if (Decls.count(VD))
20072007
FoundDecl = true;
2008+
} else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getDecl());
2009+
MD && isLambdaCallOperator(MD)) {
2010+
for (const auto &Capture : MD->getParent()->captures()) {
2011+
if (!Capture.capturesVariable())
2012+
continue;
2013+
2014+
LambdaCaptureKind CK = Capture.getCaptureKind();
2015+
if (CK != LCK_ByRef)
2016+
continue;
2017+
2018+
VarDecl *VD = dyn_cast<VarDecl>(Capture.getCapturedVar());
2019+
if (VD && Decls.count(VD))
2020+
FoundDecl = true;
2021+
}
2022+
}
20082023
}
20092024

20102025
void VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
@@ -2021,7 +2036,7 @@ namespace {
20212036

20222037
bool FoundDeclInUse() { return FoundDecl; }
20232038

2024-
}; // end class DeclMatcher
2039+
}; // end class DeclMatcher
20252040

20262041
void CheckForLoopConditionalStatement(Sema &S, Expr *Second,
20272042
Expr *Third, Stmt *Body) {

clang/test/SemaCXX/warn-loop-analysis.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,38 @@ void test10() {
299299
for (auto[i, j, k] = arr; i < a; ++i) { }
300300
for (auto[i, j, k] = arr; i < a; ++arr[0]) { }
301301
};
302+
303+
namespace GH132038 {
304+
extern void foo(int);
305+
void test1() {
306+
int a = 0;
307+
auto incr_a = [&a]() { ++a; };
308+
309+
for (int b = 10; a <= b; incr_a())
310+
foo(a);
311+
312+
for (int b = 10; a <= b;)
313+
incr_a();
314+
315+
for (int b = 10; a <= b; [&a]() { ++a; }()) { }
316+
for (int b = 10; a <= b; [&a]() { }()) { }
317+
}
318+
319+
void test2() {
320+
int a = 0;
321+
auto incr_a = [a]() { };
322+
auto incr_b = [](int b) { };
323+
324+
for (int b = 10; a <= b; incr_a()) // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}}
325+
foo(a);
326+
327+
for (int b = 10; a <= b;) // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}}
328+
incr_a();
329+
330+
for (int b = 10; a <= b; incr_b(b)) // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}}
331+
foo(a);
332+
333+
for (int b = 10; a <= b;) // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}}
334+
incr_b(b);
335+
}
336+
}

0 commit comments

Comments
 (0)