536 lines · cpp
1// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/loop-convert2 3#include "structures.h"4 5// CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})6// CHECK-MESSAGES-NOT: modernize-loop-convert7 8namespace somenamespace {9 template <class T> auto begin(T& t) -> decltype(t.begin());10 template <class T> auto begin(const T& t) -> decltype(t.begin());11 template <class T> auto end(T& t) -> decltype(t.end());12 template <class T> auto end(const T& t) -> decltype(t.end());13 template <class T> auto size(const T& t) -> decltype(t.size());14} // namespace somenamespace15 16struct SomeClass {17 template <class T> static auto begin(T& t) -> decltype(t.begin());18 template <class T> static auto begin(const T& t) -> decltype(t.begin());19 template <class T> static auto end(T& t) -> decltype(t.end());20 template <class T> static auto end(const T& t) -> decltype(t.end());21 template <class T> static auto size(const T& t) -> decltype(t.size());22};23 24namespace Negative {25 26const int N = 6;27int Arr[N] = {1, 2, 3, 4, 5, 6};28int (*pArr)[N] = &Arr;29int Sum = 0;30 31// Checks for the Index start and end:32void IndexStartAndEnd() {33 for (int I = 0; I < N + 1; ++I)34 Sum += Arr[I];35 36 for (int I = 0; I < N - 1; ++I)37 Sum += Arr[I];38 39 for (int I = 1; I < N; ++I)40 Sum += Arr[I];41 42 for (int I = 1; I < N; ++I)43 Sum += Arr[I];44 45 for (int I = 0;; ++I)46 Sum += (*pArr)[I];47}48 49// Checks for invalid increment steps:50void increment() {51 for (int I = 0; I < N; --I)52 Sum += Arr[I];53 54 for (int I = 0; I < N; I)55 Sum += Arr[I];56 57 for (int I = 0; I < N;)58 Sum += Arr[I];59 60 for (int I = 0; I < N; I += 2)61 Sum++;62}63 64// Checks to make sure that the Index isn't used outside of the array:65void IndexUse() {66 for (int I = 0; I < N; ++I)67 Arr[I] += 1 + I;68}69 70// Check for loops that don't mention arrays71void noArray() {72 for (int I = 0; I < N; ++I)73 Sum += I;74 75 for (int I = 0; I < N; ++I) {76 }77 78 for (int I = 0; I < N; ++I)79 ;80}81 82// Checks for incorrect loop variables.83void mixedVariables() {84 int BadIndex;85 for (int I = 0; BadIndex < N; ++I)86 Sum += Arr[I];87 88 for (int I = 0; I < N; ++BadIndex)89 Sum += Arr[I];90 91 for (int I = 0; BadIndex < N; ++BadIndex)92 Sum += Arr[I];93 94 for (int I = 0; BadIndex < N; ++BadIndex)95 Sum += Arr[BadIndex];96}97 98// Checks for multiple arrays Indexed.99void multipleArrays() {100 int BadArr[N];101 102 for (int I = 0; I < N; ++I)103 Sum += Arr[I] + BadArr[I];104 105 for (int I = 0; I < N; ++I) {106 int K = BadArr[I];107 Sum += Arr[I] + K;108 }109}110 111} // namespace Negative112 113namespace NegativeIterator {114 115S Ss;116T Tt;117U Tu;118 119struct BadBeginEnd : T {120 iterator notBegin();121 iterator notEnd();122 iterator begin(int);123 iterator end(int);124 iterator begin();125 iterator end();126};127 128void notBeginOrEnd() {129 BadBeginEnd Bad;130 for (T::iterator I = Bad.notBegin(), E = Bad.end(); I != E; ++I)131 int K = *I;132 133 for (T::iterator I = Bad.begin(), E = Bad.notEnd(); I != E; ++I)134 int K = *I;135 136 for (T::iterator I = Bad.begin(0), E = Bad.end(0); I != E; ++I)137 int K = *I;138}139 140void badLoopShapes() {141 for (T::iterator I = Tt.begin(), E = Tt.end(), F = E; I != E; ++I)142 int K = *I;143 144 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E;)145 int K = *I;146 147 for (T::iterator I = Tt.begin(), E = Tt.end();; ++I)148 int K = *I;149 150 T::iterator OutsideI;151 T::iterator OutsideE;152 153 for (; OutsideI != OutsideE; ++OutsideI)154 int K = *OutsideI;155}156 157void iteratorArrayMix() {158 int Lower;159 const int N = 6;160 for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++I)161 int K = *I;162 163 for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++Lower)164 int K = *I;165}166 167struct ExtraConstructor : T::iterator {168 ExtraConstructor(T::iterator, int);169 explicit ExtraConstructor(T::iterator);170};171 172void badConstructor() {173 for (T::iterator I = ExtraConstructor(Tt.begin(), 0), E = Tt.end();174 I != E; ++I)175 int K = *I;176 for (T::iterator I = ExtraConstructor(Tt.begin()), E = Tt.end(); I != E; ++I)177 int K = *I;178}179 180void foo(S::iterator It) {}181class Foo {public: void bar(S::iterator It); };182Foo Fo;183 184void iteratorUsed() {185 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)186 foo(I);187 188 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)189 Fo.bar(I);190 191 S::iterator Ret;192 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)193 Ret = I;194}195 196void iteratorMemberUsed() {197 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)198 I.X = *I;199 200 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)201 int K = I.X + *I;202 203 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)204 int K = E.X + *I;205}206 207void iteratorMethodCalled() {208 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)209 I.insert(3);210 211 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)212 if (I != I)213 int K = 3;214}215 216void iteratorOperatorCalled() {217 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)218 int K = *(++I);219 220 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)221 MutableVal K = *(++I);222}223 224void differentContainers() {225 T Other;226 for (T::iterator I = Tt.begin(), E = Other.end(); I != E; ++I)227 int K = *I;228 for (T::iterator I = begin(Tt), E = end(Other); I != E; ++I)229 int K = *I;230 231 for (T::iterator I = Other.begin(), E = Tt.end(); I != E; ++I)232 int K = *I;233 234 S OtherS;235 for (S::iterator I = Ss.begin(), E = OtherS.end(); I != E; ++I)236 MutableVal K = *I;237 238 for (S::iterator I = OtherS.begin(), E = Ss.end(); I != E; ++I)239 MutableVal K = *I;240}241 242void mixedMemberAndADL() {243 for (T::iterator I = Tt.begin(), E = end(Tt); I != E; ++I)244 int K = *I;245 for (T::iterator I = begin(Tt), E = Tt.end(); I != E; ++I)246 int K = *I;247 for (T::iterator I = std::begin(Tt), E = Tt.end(); I != E; ++I)248 int K = *I;249 for (T::iterator I = std::begin(Tt), E = end(Tt); I != E; ++I)250 int K = *I;251}252 253void nonADLOrStdCalls() {254 for (T::iterator I = SomeClass::begin(Tt), E = SomeClass::end(Tt); I != E; ++I)255 int K = *I;256 for (T::iterator I = somenamespace::begin(Tt), E = somenamespace::end(Tt); I != E; ++I)257 int K = *I;258}259 260void wrongIterators() {261 T::iterator Other;262 for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)263 int K = *I;264}265 266struct EvilArrow : U {267 // Please, no one ever write code like this.268 U *operator->();269};270 271void differentMemberAccessTypes() {272 EvilArrow A;273 for (EvilArrow::iterator I = A.begin(), E = A->end(); I != E; ++I)274 Val K = *I;275 for (EvilArrow::iterator I = A->begin(), E = A.end(); I != E; ++I)276 Val K = *I;277}278 279void f(const T::iterator &It, int);280void f(const T &It, int);281void g(T &It, int);282 283void iteratorPassedToFunction() {284 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)285 f(I, *I);286}287 288// FIXME: These tests can be removed if this tool ever does enough analysis to289// decide that this is a safe transformation. Until then, we don't want it290// applied.291void iteratorDefinedOutside() {292 T::iterator TheEnd = Tt.end();293 for (T::iterator I = Tt.begin(); I != TheEnd; ++I)294 int K = *I;295 296 T::iterator TheBegin = Tt.begin();297 for (T::iterator E = Tt.end(); TheBegin != E; ++TheBegin)298 int K = *TheBegin;299}300 301} // namespace NegativeIterator302 303namespace NegativePseudoArray {304 305const int N = 6;306dependent<int> V;307dependent<int> *Pv;308 309int Sum = 0;310 311// Checks for the Index start and end:312void IndexStartAndEnd() {313 for (int I = 0; I < V.size() + 1; ++I)314 Sum += V[I];315 316 for (int I = 0; I < V.size() - 1; ++I)317 Sum += V[I];318 319 for (int I = 1; I < V.size(); ++I)320 Sum += V[I];321 322 for (int I = 1; I < V.size(); ++I)323 Sum += V[I];324 325 for (int I = 0;; ++I)326 Sum += (*Pv)[I];327}328 329// Checks for invalid increment steps:330void increment() {331 for (int I = 0; I < V.size(); --I)332 Sum += V[I];333 334 for (int I = 0; I < V.size(); I)335 Sum += V[I];336 337 for (int I = 0; I < V.size();)338 Sum += V[I];339 340 for (int I = 0; I < V.size(); I += 2)341 Sum++;342}343 344// Checks to make sure that the Index isn't used outside of the container:345void IndexUse() {346 for (int I = 0; I < V.size(); ++I)347 V[I] += 1 + I;348}349 350// Checks for incorrect loop variables.351void mixedVariables() {352 int BadIndex;353 for (int I = 0; BadIndex < V.size(); ++I)354 Sum += V[I];355 356 for (int I = 0; I < V.size(); ++BadIndex)357 Sum += V[I];358 359 for (int I = 0; BadIndex < V.size(); ++BadIndex)360 Sum += V[I];361 362 for (int I = 0; BadIndex < V.size(); ++BadIndex)363 Sum += V[BadIndex];364}365 366// Checks for an array Indexed in addition to the container.367void multipleArrays() {368 int BadArr[N];369 370 for (int I = 0; I < V.size(); ++I)371 Sum += V[I] + BadArr[I];372 373 for (int I = 0; I < V.size(); ++I)374 Sum += BadArr[I];375 376 for (int I = 0; I < V.size(); ++I) {377 int K = BadArr[I];378 Sum += K + 2;379 }380 381 for (int I = 0; I < V.size(); ++I) {382 int K = BadArr[I];383 Sum += V[I] + K;384 }385}386 387// Checks for multiple containers being Indexed container.388void multipleContainers() {389 dependent<int> BadArr;390 391 for (int I = 0; I < V.size(); ++I)392 Sum += V[I] + BadArr[I];393 394 for (int I = 0; I < V.size(); ++I)395 Sum += BadArr[I];396 397 for (int I = 0; I < V.size(); ++I) {398 int K = BadArr[I];399 Sum += K + 2;400 }401 402 for (int I = 0; I < V.size(); ++I) {403 int K = BadArr[I];404 Sum += V[I] + K;405 }406}407 408// Check to make sure that dereferenced pointers-to-containers behave nicely.409void derefContainer() {410 // Note the dependent<T>::operator*() returns another dependent<T>.411 // This test makes sure that we don't allow an arbitrary number of *'s.412 for (int I = 0; I < Pv->size(); ++I)413 Sum += (**Pv).at(I);414 415 for (int I = 0; I < Pv->size(); ++I)416 Sum += (**Pv)[I];417}418 419void wrongEnd() {420 int Bad;421 for (int I = 0, E = V.size(); I < Bad; ++I)422 Sum += V[I];423}424 425void nonADLOrStdCalls() {426 for (int I = 0, E = somenamespace::size(V); E != I; ++I)427 printf("Fibonacci number is %d\n", V[I]);428 for (int I = 0, E = SomeClass::size(V); E != I; ++I)429 printf("Fibonacci number is %d\n", V[I]);430}431 432// Checks to see that non-const member functions are not called on the container433// object.434// These could be conceivably allowed with a lower required confidence level.435void memberFunctionCalled() {436 for (int I = 0; I < V.size(); ++I) {437 Sum += V[I];438 V.foo();439 }440 441 for (int I = 0; I < V.size(); ++I) {442 Sum += V[I];443 dependent<int>::iterator It = V.begin();444 }445}446 447} // namespace NegativePseudoArray448 449namespace NegativeMultiEndCall {450 451S Ss;452T Tt;453U Uu;454 455void f(X);456void f(S);457void f(T);458 459void complexContainer() {460 X Xx;461 for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end(); I != E; ++I) {462 f(Xx);463 MutableVal K = *I;464 }465 466 for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end(); I != E; ++I) {467 f(Xx);468 int K = *I;469 }470 471 for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end(); I != E; ++I) {472 f(Xx.Ss);473 MutableVal K = *I;474 }475 476 for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end(); I != E; ++I) {477 f(Xx.Tt);478 int K = *I;479 }480 481 for (S::iterator I = Xx.getS().begin(), E = Xx.getS().end(); I != E; ++I) {482 f(Xx.getS());483 MutableVal K = *I;484 }485 486 X Exes[5];487 int Index = 0;488 489 for (S::iterator I = Exes[Index].getS().begin(),490 E = Exes[Index].getS().end();491 I != E; ++I) {492 Index++;493 MutableVal K = *I;494 }495}496 497} // namespace NegativeMultiEndCall498 499namespace NoUsages {500 501const int N = 6;502int Arr[N] = {1, 2, 3, 4, 5, 6};503S Ss;504dependent<int> V;505int Count = 0;506 507void foo();508 509void f() {510 for (int I = 0; I < N; ++I) {}511 for (int I = 0; I < N; ++I)512 printf("Hello world\n");513 for (int I = 0; I < N; ++I)514 ++Count;515 for (int I = 0; I < N; ++I)516 foo();517 518 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) {}519 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)520 printf("Hello world\n");521 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)522 ++Count;523 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)524 foo();525 526 for (int I = 0; I < V.size(); ++I) {}527 for (int I = 0; I < V.size(); ++I)528 printf("Hello world\n");529 for (int I = 0; I < V.size(); ++I)530 ++Count;531 for (int I = 0; I < V.size(); ++I)532 foo();533}534 535} // namespace NoUsages536