Skip to content

Commit a85eb11

Browse files
committed
[clang-tidy] Extend LoopConvert on array with != comparison
Enables transforming loops of the form: ``` for (int i = 0; I != container.size(); ++I) { container[I]...; } for (int i = 0; I != N; ++I) { FixedArrSizeN[I]...; } ``` Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D97940
1 parent f2b749b commit a85eb11

File tree

2 files changed

+81
-28
lines changed

2 files changed

+81
-28
lines changed

clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,17 @@ static const StatementMatcher incrementVarMatcher() {
8383
return declRefExpr(to(varDecl(equalsBoundNode(InitVarName))));
8484
}
8585

86+
static StatementMatcher
87+
arrayConditionMatcher(internal::Matcher<Expr> LimitExpr) {
88+
return binaryOperator(
89+
anyOf(allOf(hasOperatorName("<"), hasLHS(integerComparisonMatcher()),
90+
hasRHS(LimitExpr)),
91+
allOf(hasOperatorName(">"), hasLHS(LimitExpr),
92+
hasRHS(integerComparisonMatcher())),
93+
allOf(hasOperatorName("!="),
94+
hasOperands(integerComparisonMatcher(), LimitExpr))));
95+
}
96+
8697
/// The matcher for loops over arrays.
8798
/// \code
8899
/// for (int i = 0; i < 3 + 2; ++i) { ... }
@@ -99,18 +110,12 @@ StatementMatcher makeArrayLoopMatcher() {
99110
StatementMatcher ArrayBoundMatcher =
100111
expr(hasType(isInteger())).bind(ConditionBoundName);
101112

102-
return forStmt(
103-
unless(isInTemplateInstantiation()),
104-
hasLoopInit(declStmt(hasSingleDecl(initToZeroMatcher()))),
105-
hasCondition(anyOf(
106-
binaryOperator(hasOperatorName("<"),
107-
hasLHS(integerComparisonMatcher()),
108-
hasRHS(ArrayBoundMatcher)),
109-
binaryOperator(hasOperatorName(">"), hasLHS(ArrayBoundMatcher),
110-
hasRHS(integerComparisonMatcher())))),
111-
hasIncrement(
112-
unaryOperator(hasOperatorName("++"),
113-
hasUnaryOperand(incrementVarMatcher()))))
113+
return forStmt(unless(isInTemplateInstantiation()),
114+
hasLoopInit(declStmt(hasSingleDecl(initToZeroMatcher()))),
115+
hasCondition(arrayConditionMatcher(ArrayBoundMatcher)),
116+
hasIncrement(
117+
unaryOperator(hasOperatorName("++"),
118+
hasUnaryOperand(incrementVarMatcher()))))
114119
.bind(LoopNameArray);
115120
}
116121

@@ -278,22 +283,16 @@ StatementMatcher makePseudoArrayLoopMatcher() {
278283
declRefExpr(to(varDecl(equalsBoundNode(EndVarName))))),
279284
EndInitMatcher));
280285

281-
return forStmt(
282-
unless(isInTemplateInstantiation()),
283-
hasLoopInit(
284-
anyOf(declStmt(declCountIs(2),
285-
containsDeclaration(0, initToZeroMatcher()),
286-
containsDeclaration(1, EndDeclMatcher)),
287-
declStmt(hasSingleDecl(initToZeroMatcher())))),
288-
hasCondition(anyOf(
289-
binaryOperator(hasOperatorName("<"),
290-
hasLHS(integerComparisonMatcher()),
291-
hasRHS(IndexBoundMatcher)),
292-
binaryOperator(hasOperatorName(">"), hasLHS(IndexBoundMatcher),
293-
hasRHS(integerComparisonMatcher())))),
294-
hasIncrement(
295-
unaryOperator(hasOperatorName("++"),
296-
hasUnaryOperand(incrementVarMatcher()))))
286+
return forStmt(unless(isInTemplateInstantiation()),
287+
hasLoopInit(
288+
anyOf(declStmt(declCountIs(2),
289+
containsDeclaration(0, initToZeroMatcher()),
290+
containsDeclaration(1, EndDeclMatcher)),
291+
declStmt(hasSingleDecl(initToZeroMatcher())))),
292+
hasCondition(arrayConditionMatcher(IndexBoundMatcher)),
293+
hasIncrement(
294+
unaryOperator(hasOperatorName("++"),
295+
hasUnaryOperand(incrementVarMatcher()))))
297296
.bind(LoopNamePseudoArray);
298297
}
299298

clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-basic.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,33 @@ void f() {
9595
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
9696
// CHECK-FIXES: for (auto & Tea : Teas)
9797
// CHECK-FIXES-NEXT: Tea.g();
98+
99+
for (int I = 0; N > I; ++I) {
100+
printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
101+
Sum += Arr[I] + 2;
102+
}
103+
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
104+
// CHECK-FIXES: for (int & I : Arr)
105+
// CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
106+
// CHECK-FIXES-NEXT: Sum += I + 2;
107+
108+
for (int I = 0; N != I; ++I) {
109+
printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
110+
Sum += Arr[I] + 2;
111+
}
112+
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
113+
// CHECK-FIXES: for (int & I : Arr)
114+
// CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
115+
// CHECK-FIXES-NEXT: Sum += I + 2;
116+
117+
for (int I = 0; I != N; ++I) {
118+
printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
119+
Sum += Arr[I] + 2;
120+
}
121+
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
122+
// CHECK-FIXES: for (int & I : Arr)
123+
// CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
124+
// CHECK-FIXES-NEXT: Sum += I + 2;
98125
}
99126

100127
const int *constArray() {
@@ -589,6 +616,33 @@ void f() {
589616
// CHECK-FIXES: for (int I : *Cv)
590617
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
591618
// CHECK-FIXES-NEXT: Sum += I + 2;
619+
620+
for (int I = 0, E = V.size(); E > I; ++I) {
621+
printf("Fibonacci number is %d\n", V[I]);
622+
Sum += V[I] + 2;
623+
}
624+
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
625+
// CHECK-FIXES: for (int I : V)
626+
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
627+
// CHECK-FIXES-NEXT: Sum += I + 2;
628+
629+
for (int I = 0, E = V.size(); I != E; ++I) {
630+
printf("Fibonacci number is %d\n", V[I]);
631+
Sum += V[I] + 2;
632+
}
633+
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
634+
// CHECK-FIXES: for (int I : V)
635+
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
636+
// CHECK-FIXES-NEXT: Sum += I + 2;
637+
638+
for (int I = 0, E = V.size(); E != I; ++I) {
639+
printf("Fibonacci number is %d\n", V[I]);
640+
Sum += V[I] + 2;
641+
}
642+
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
643+
// CHECK-FIXES: for (int I : V)
644+
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
645+
// CHECK-FIXES-NEXT: Sum += I + 2;
592646
}
593647

594648
// Ensure that 'const auto &' is used with containers of non-trivial types.

0 commit comments

Comments
 (0)