Skip to content

Commit 70f4c6e

Browse files
author
Adam Balogh
committed
[clan-tidy] Fix false positive in bugprone-infinite-loop
The checker bugprone-infinite-loop does not track changes of variables in the initialization expression of a variable declared inside the condition of the while statement. This leads to false positives, similarly to the one in the bug report https://bugs.llvm.org/show_bug.cgi?id=44618. This patch fixes this issue by enabling tracking of the variables of this expression as well. Differential Revision: https://reviews.llvm.org/D73270
1 parent cbf03ae commit 70f4c6e

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,17 +170,33 @@ void InfiniteLoopCheck::check(const MatchFinder::MatchResult &Result) {
170170
const auto *LoopStmt = Result.Nodes.getNodeAs<Stmt>("loop-stmt");
171171
const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
172172

173+
bool ShouldHaveConditionVariables = true;
174+
if (const auto *While = dyn_cast<WhileStmt>(LoopStmt)) {
175+
if (const VarDecl *LoopVarDecl = While->getConditionVariable()) {
176+
if (const Expr *Init = LoopVarDecl->getInit()) {
177+
ShouldHaveConditionVariables = false;
178+
Cond = Init;
179+
}
180+
}
181+
}
182+
173183
if (isAtLeastOneCondVarChanged(Func, LoopStmt, Cond, Result.Context))
174184
return;
175185

176186
std::string CondVarNames = getCondVarNames(Cond);
177-
if (CondVarNames.empty())
187+
if (ShouldHaveConditionVariables && CondVarNames.empty())
178188
return;
179189

180-
diag(LoopStmt->getBeginLoc(),
181-
"this loop is infinite; none of its condition variables (%0)"
182-
" are updated in the loop body")
190+
if (CondVarNames.empty()) {
191+
diag(LoopStmt->getBeginLoc(),
192+
"this loop is infinite; it does not check any variables in the"
193+
" condition");
194+
} else {
195+
diag(LoopStmt->getBeginLoc(),
196+
"this loop is infinite; none of its condition variables (%0)"
197+
" are updated in the loop body")
183198
<< CondVarNames;
199+
}
184200
}
185201

186202
} // namespace bugprone

clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,20 @@ void simple_infinite_loop1() {
44
int i = 0;
55
int j = 0;
66
while (i < 10) {
7-
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop]
7+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop]
88
j++;
99
}
1010

11+
while (int k = 10) {
12+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; it does not check any variables in the condition [bugprone-infinite-loop]
13+
j--;
14+
}
15+
16+
while (int k = 10) {
17+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; it does not check any variables in the condition [bugprone-infinite-loop]
18+
k--;
19+
}
20+
1121
do {
1222
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop]
1323
j++;
@@ -27,6 +37,16 @@ void simple_infinite_loop2() {
2737
j++;
2838
}
2939

40+
while (int k = Limit) {
41+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (Limit) are updated in the loop body [bugprone-infinite-loop]
42+
j--;
43+
}
44+
45+
while (int k = Limit) {
46+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (Limit) are updated in the loop body [bugprone-infinite-loop]
47+
k--;
48+
}
49+
3050
do {
3151
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i, Limit) are updated in the loop body [bugprone-infinite-loop]
3252
j++;
@@ -44,6 +64,22 @@ void simple_not_infinite1() {
4464
// Not an error since 'Limit' is updated.
4565
Limit--;
4666
}
67+
68+
while (Limit--) {
69+
// Not an error since 'Limit' is updated.
70+
i++;
71+
}
72+
73+
while (int k = Limit) {
74+
// Not an error since 'Limit' is updated.
75+
Limit--;
76+
}
77+
78+
while (int k = Limit--) {
79+
// Not an error since 'Limit' is updated.
80+
i++;
81+
}
82+
4783
do {
4884
Limit--;
4985
} while (i < Limit);

0 commit comments

Comments
 (0)