xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp (revision e43295209bb86e93008363c66c1277c7d8bb148c)
189a1d03eSRichard // RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/loop-convert
289a1d03eSRichard 
389a1d03eSRichard #include "structures.h"
489a1d03eSRichard 
589a1d03eSRichard namespace Array {
689a1d03eSRichard 
789a1d03eSRichard const int N = 6;
889a1d03eSRichard const int NMinusOne = N - 1;
989a1d03eSRichard int Arr[N] = {1, 2, 3, 4, 5, 6};
1089a1d03eSRichard const int ConstArr[N] = {1, 2, 3, 4, 5, 6};
1189a1d03eSRichard int (*PArr)[N] = &Arr;
1289a1d03eSRichard 
1389a1d03eSRichard void f() {
1489a1d03eSRichard   int Sum = 0;
1589a1d03eSRichard 
1689a1d03eSRichard   for (int I = 0; I < N; ++I) {
1789a1d03eSRichard     Sum += Arr[I];
1889a1d03eSRichard     int K;
1989a1d03eSRichard   }
2089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead [modernize-loop-convert]
2189a1d03eSRichard   // CHECK-FIXES: for (int I : Arr)
2289a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I;
2389a1d03eSRichard   // CHECK-FIXES-NEXT: int K;
2489a1d03eSRichard 
2589a1d03eSRichard   for (int I = 0; I < N; ++I) {
2689a1d03eSRichard     printf("Fibonacci number is %d\n", Arr[I]);
2789a1d03eSRichard     Sum += Arr[I] + 2;
2889a1d03eSRichard   }
2989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
3089a1d03eSRichard   // CHECK-FIXES: for (int I : Arr)
3189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
3289a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
3389a1d03eSRichard 
3489a1d03eSRichard   for (int I = 0; I < N; ++I) {
3589a1d03eSRichard     int X = Arr[I];
3689a1d03eSRichard     int Y = Arr[I] + 2;
3789a1d03eSRichard   }
3889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
3989a1d03eSRichard   // CHECK-FIXES: for (int I : Arr)
4089a1d03eSRichard   // CHECK-FIXES-NEXT: int X = I;
4189a1d03eSRichard   // CHECK-FIXES-NEXT: int Y = I + 2;
4289a1d03eSRichard 
4389a1d03eSRichard   for (int I = 0; I < N; ++I) {
4489a1d03eSRichard     int X = N;
4589a1d03eSRichard     X = Arr[I];
4689a1d03eSRichard   }
4789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
4889a1d03eSRichard   // CHECK-FIXES: for (int I : Arr)
4989a1d03eSRichard   // CHECK-FIXES-NEXT: int X = N;
5089a1d03eSRichard   // CHECK-FIXES-NEXT: X = I;
5189a1d03eSRichard 
5289a1d03eSRichard   for (int I = 0; I < N; ++I) {
5389a1d03eSRichard     Arr[I] += 1;
5489a1d03eSRichard   }
5589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
5689a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
5789a1d03eSRichard   // CHECK-FIXES-NEXT: I += 1;
5889a1d03eSRichard 
5989a1d03eSRichard   for (int I = 0; I < N; ++I) {
6089a1d03eSRichard     int X = Arr[I] + 2;
6189a1d03eSRichard     Arr[I]++;
6289a1d03eSRichard   }
6389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
6489a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
6589a1d03eSRichard   // CHECK-FIXES-NEXT: int X = I + 2;
6689a1d03eSRichard   // CHECK-FIXES-NEXT: I++;
6789a1d03eSRichard 
6889a1d03eSRichard   for (int I = 0; I < N; ++I) {
6989a1d03eSRichard     Arr[I] = 4 + Arr[I];
7089a1d03eSRichard   }
7189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
7289a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
7389a1d03eSRichard   // CHECK-FIXES-NEXT: I = 4 + I;
7489a1d03eSRichard 
7589a1d03eSRichard   for (int I = 0; I < NMinusOne + 1; ++I) {
7689a1d03eSRichard     Sum += Arr[I];
7789a1d03eSRichard   }
7889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
7989a1d03eSRichard   // CHECK-FIXES: for (int I : Arr)
8089a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I;
8189a1d03eSRichard 
8289a1d03eSRichard   for (int I = 0; I < N; ++I) {
8389a1d03eSRichard     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
8489a1d03eSRichard     Sum += Arr[I] + 2;
8589a1d03eSRichard   }
8689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
8789a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
8889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
8989a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
9089a1d03eSRichard 
9189a1d03eSRichard   Val Teas[N];
9289a1d03eSRichard   for (int I = 0; I < N; ++I) {
9389a1d03eSRichard     Teas[I].g();
9489a1d03eSRichard   }
9589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
9689a1d03eSRichard   // CHECK-FIXES: for (auto & Tea : Teas)
9789a1d03eSRichard   // CHECK-FIXES-NEXT: Tea.g();
9889a1d03eSRichard 
9989a1d03eSRichard   for (int I = 0; N > I; ++I) {
10089a1d03eSRichard     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
10189a1d03eSRichard     Sum += Arr[I] + 2;
10289a1d03eSRichard   }
10389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
10489a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
10589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
10689a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
10789a1d03eSRichard 
10889a1d03eSRichard   for (int I = 0; N != I; ++I) {
10989a1d03eSRichard     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
11089a1d03eSRichard     Sum += Arr[I] + 2;
11189a1d03eSRichard   }
11289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
11389a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
11489a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
11589a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
11689a1d03eSRichard 
11789a1d03eSRichard   for (int I = 0; I != N; ++I) {
11889a1d03eSRichard     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
11989a1d03eSRichard     Sum += Arr[I] + 2;
12089a1d03eSRichard   }
12189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
12289a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
12389a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
12489a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
12589a1d03eSRichard }
12689a1d03eSRichard 
12789a1d03eSRichard const int *constArray() {
12889a1d03eSRichard   for (int I = 0; I < N; ++I) {
12989a1d03eSRichard     printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
13089a1d03eSRichard   }
13189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
13289a1d03eSRichard   // CHECK-FIXES: for (int I : ConstArr)
13389a1d03eSRichard   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I);
13489a1d03eSRichard 
13589a1d03eSRichard   const NonTriviallyCopyable NonCopy[N]{};
13689a1d03eSRichard   for (int I = 0; I < N; ++I) {
13789a1d03eSRichard     printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
13889a1d03eSRichard   }
13989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
14089a1d03eSRichard   // CHECK-FIXES: for (const auto & I : NonCopy)
14189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
14289a1d03eSRichard 
14389a1d03eSRichard   const TriviallyCopyableButBig Big[N]{};
14489a1d03eSRichard   for (int I = 0; I < N; ++I) {
14589a1d03eSRichard     printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X);
14689a1d03eSRichard   }
14789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
14889a1d03eSRichard   // CHECK-FIXES: for (const auto & I : Big)
14989a1d03eSRichard   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
15089a1d03eSRichard 
15189a1d03eSRichard   bool Something = false;
15289a1d03eSRichard   for (int I = 0; I < N; ++I) {
15389a1d03eSRichard     if (Something)
15489a1d03eSRichard       return &ConstArr[I];
15589a1d03eSRichard   }
15689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
15789a1d03eSRichard   // CHECK-FIXES: for (const int & I : ConstArr)
15889a1d03eSRichard   // CHECK-FIXES-NEXT: if (Something)
15989a1d03eSRichard   // CHECK-FIXES-NEXT: return &I;
16089a1d03eSRichard }
16189a1d03eSRichard 
16289a1d03eSRichard struct HasArr {
16389a1d03eSRichard   int Arr[N];
16489a1d03eSRichard   Val ValArr[N];
16589a1d03eSRichard   void implicitThis() {
16689a1d03eSRichard     for (int I = 0; I < N; ++I) {
16789a1d03eSRichard       printf("%d", Arr[I]);
16889a1d03eSRichard     }
16989a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
17089a1d03eSRichard     // CHECK-FIXES: for (int I : Arr)
17189a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I);
17289a1d03eSRichard 
17389a1d03eSRichard     for (int I = 0; I < N; ++I) {
17489a1d03eSRichard       printf("%d", ValArr[I].X);
17589a1d03eSRichard     }
17689a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
17789a1d03eSRichard     // CHECK-FIXES: for (auto & I : ValArr)
17889a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I.X);
17989a1d03eSRichard   }
18089a1d03eSRichard 
18189a1d03eSRichard   void explicitThis() {
18289a1d03eSRichard     for (int I = 0; I < N; ++I) {
18389a1d03eSRichard       printf("%d", this->Arr[I]);
18489a1d03eSRichard     }
18589a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
18689a1d03eSRichard     // CHECK-FIXES: for (int I : this->Arr)
18789a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I);
18889a1d03eSRichard 
18989a1d03eSRichard     for (int I = 0; I < N; ++I) {
19089a1d03eSRichard       printf("%d", this->ValArr[I].X);
19189a1d03eSRichard     }
19289a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
19389a1d03eSRichard     // CHECK-FIXES: for (auto & I : this->ValArr)
19489a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I.X);
19589a1d03eSRichard   }
19689a1d03eSRichard };
19789a1d03eSRichard 
19889a1d03eSRichard struct HasIndirectArr {
19989a1d03eSRichard   HasArr HA;
20089a1d03eSRichard   void implicitThis() {
20189a1d03eSRichard     for (int I = 0; I < N; ++I) {
20289a1d03eSRichard       printf("%d", HA.Arr[I]);
20389a1d03eSRichard     }
20489a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
20589a1d03eSRichard     // CHECK-FIXES: for (int I : HA.Arr)
20689a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I);
20789a1d03eSRichard 
20889a1d03eSRichard     for (int I = 0; I < N; ++I) {
20989a1d03eSRichard       printf("%d", HA.ValArr[I].X);
21089a1d03eSRichard     }
21189a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
21289a1d03eSRichard     // CHECK-FIXES: for (auto & I : HA.ValArr)
21389a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I.X);
21489a1d03eSRichard   }
21589a1d03eSRichard 
21689a1d03eSRichard   void explicitThis() {
21789a1d03eSRichard     for (int I = 0; I < N; ++I) {
21889a1d03eSRichard       printf("%d", this->HA.Arr[I]);
21989a1d03eSRichard     }
22089a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
22189a1d03eSRichard     // CHECK-FIXES: for (int I : this->HA.Arr)
22289a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I);
22389a1d03eSRichard 
22489a1d03eSRichard     for (int I = 0; I < N; ++I) {
22589a1d03eSRichard       printf("%d", this->HA.ValArr[I].X);
22689a1d03eSRichard     }
22789a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
22889a1d03eSRichard     // CHECK-FIXES: for (auto & I : this->HA.ValArr)
22989a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I.X);
23089a1d03eSRichard   }
23189a1d03eSRichard };
23289a1d03eSRichard 
23389a1d03eSRichard // Loops whose bounds are value-dependent should not be converted.
23489a1d03eSRichard template <int N>
23589a1d03eSRichard void dependentExprBound() {
23689a1d03eSRichard   for (int I = 0; I < N; ++I)
23789a1d03eSRichard     Arr[I] = 0;
23889a1d03eSRichard }
23989a1d03eSRichard template void dependentExprBound<20>();
24089a1d03eSRichard 
24189a1d03eSRichard void memberFunctionPointer() {
24289a1d03eSRichard   Val V;
24389a1d03eSRichard   void (Val::*mfpArr[N])(void) = {&Val::g};
24489a1d03eSRichard   for (int I = 0; I < N; ++I)
24589a1d03eSRichard     (V.*mfpArr[I])();
24689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
24789a1d03eSRichard   // CHECK-FIXES: for (auto & I : mfpArr)
24889a1d03eSRichard   // CHECK-FIXES-NEXT: (V.*I)();
24989a1d03eSRichard 
25089a1d03eSRichard   struct Foo {
25189a1d03eSRichard     int (Val::*f)();
25289a1d03eSRichard   } Foo[N];
25389a1d03eSRichard 
25489a1d03eSRichard   for (int I = 0; I < N; ++I)
25589a1d03eSRichard     int R = (V.*(Foo[I].f))();
25689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
25789a1d03eSRichard   // CHECK-FIXES: for (auto & I : Foo)
25889a1d03eSRichard   // CHECK-FIXES-NEXT: int R = (V.*(I.f))();
25989a1d03eSRichard 
26089a1d03eSRichard }
26189a1d03eSRichard 
26289a1d03eSRichard } // namespace Array
26389a1d03eSRichard 
26489a1d03eSRichard namespace Iterator {
26589a1d03eSRichard 
26689a1d03eSRichard void f() {
26789a1d03eSRichard   /// begin()/end() - based for loops here:
26889a1d03eSRichard   T Tt;
26989a1d03eSRichard   for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) {
27089a1d03eSRichard     printf("I found %d\n", *It);
27189a1d03eSRichard   }
27289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
27389a1d03eSRichard   // CHECK-FIXES: for (int & It : Tt)
27489a1d03eSRichard   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
27589a1d03eSRichard 
27689a1d03eSRichard   // Do not crash because of Qq.begin() converting. Q::iterator converts with a
27789a1d03eSRichard   // conversion operator, which has no name, to Q::const_iterator.
27889a1d03eSRichard   Q Qq;
27989a1d03eSRichard   for (Q::const_iterator It = Qq.begin(), E = Qq.end(); It != E; ++It) {
28089a1d03eSRichard     printf("I found %d\n", *It);
28189a1d03eSRichard   }
28289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
28389a1d03eSRichard   // CHECK-FIXES: for (int & It : Qq)
28489a1d03eSRichard   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
28589a1d03eSRichard 
28689a1d03eSRichard   T *Pt;
28789a1d03eSRichard   for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
28889a1d03eSRichard     printf("I found %d\n", *It);
28989a1d03eSRichard   }
29089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
29189a1d03eSRichard   // CHECK-FIXES: for (int & It : *Pt)
29289a1d03eSRichard   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
29389a1d03eSRichard 
29489a1d03eSRichard   S Ss;
29589a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
29689a1d03eSRichard     printf("s has value %d\n", (*It).X);
29789a1d03eSRichard   }
29889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
29989a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
30089a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
30189a1d03eSRichard 
30289a1d03eSRichard   S *Ps;
30389a1d03eSRichard   for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
30489a1d03eSRichard     printf("s has value %d\n", (*It).X);
30589a1d03eSRichard   }
30689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
30789a1d03eSRichard   // CHECK-FIXES: for (auto & P : *Ps)
30889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
30989a1d03eSRichard 
31089a1d03eSRichard   for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
31189a1d03eSRichard     printf("s has value %d\n", (*It).X);
31289a1d03eSRichard   }
31389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
31489a1d03eSRichard   // CHECK-FIXES: for (auto It : Ss)
31589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
31689a1d03eSRichard 
31789a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
31889a1d03eSRichard     printf("s has value %d\n", It->X);
31989a1d03eSRichard   }
32089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
32189a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
32289a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
32389a1d03eSRichard 
32489a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
32589a1d03eSRichard     It->X = 3;
32689a1d03eSRichard   }
32789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
32889a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
32989a1d03eSRichard   // CHECK-FIXES-NEXT: It.X = 3;
33089a1d03eSRichard 
33189a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
33289a1d03eSRichard     (*It).X = 3;
33389a1d03eSRichard   }
33489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
33589a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
33689a1d03eSRichard   // CHECK-FIXES-NEXT: It.X = 3;
33789a1d03eSRichard 
33889a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
33989a1d03eSRichard     It->nonConstFun(4, 5);
34089a1d03eSRichard   }
34189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
34289a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
34389a1d03eSRichard   // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
34489a1d03eSRichard 
34589a1d03eSRichard   U Uu;
34689a1d03eSRichard   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
34789a1d03eSRichard     printf("s has value %d\n", It->X);
34889a1d03eSRichard   }
34989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
35089a1d03eSRichard   // CHECK-FIXES: for (auto & It : Uu)
35189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
35289a1d03eSRichard 
35389a1d03eSRichard   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
35489a1d03eSRichard     printf("s has value %d\n", (*It).X);
35589a1d03eSRichard   }
35689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
35789a1d03eSRichard   // CHECK-FIXES: for (auto & It : Uu)
35889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
35989a1d03eSRichard 
36089a1d03eSRichard   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
36189a1d03eSRichard     Val* a = It.operator->();
36289a1d03eSRichard   }
36389a1d03eSRichard 
36489a1d03eSRichard   U::iterator A;
36589a1d03eSRichard   for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)
36689a1d03eSRichard     int K = A->X + I->X;
36789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
36889a1d03eSRichard   // CHECK-FIXES: for (auto & I : Uu)
36989a1d03eSRichard   // CHECK-FIXES-NEXT: int K = A->X + I.X;
37089a1d03eSRichard 
37189a1d03eSRichard   dependent<int> V;
37289a1d03eSRichard   for (dependent<int>::iterator It = V.begin(), E = V.end();
37389a1d03eSRichard        It != E; ++It) {
37489a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
37589a1d03eSRichard   }
37689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
37789a1d03eSRichard   // CHECK-FIXES: for (int & It : V)
37889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
37989a1d03eSRichard 
38089a1d03eSRichard   for (dependent<int>::iterator It(V.begin()), E = V.end();
38189a1d03eSRichard        It != E; ++It) {
38289a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
38389a1d03eSRichard   }
38489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
38589a1d03eSRichard   // CHECK-FIXES: for (int & It : V)
38689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
38789a1d03eSRichard 
38889a1d03eSRichard   doublyDependent<int, int> Intmap;
38989a1d03eSRichard   for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();
39089a1d03eSRichard        It != E; ++It) {
39189a1d03eSRichard     printf("Intmap[%d] = %d", It->first, It->second);
39289a1d03eSRichard   }
39389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
39489a1d03eSRichard   // CHECK-FIXES: for (auto & It : Intmap)
39589a1d03eSRichard   // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);
39689a1d03eSRichard 
39789a1d03eSRichard   // PtrSet's iterator dereferences by value so auto & can't be used.
39889a1d03eSRichard   {
39989a1d03eSRichard     PtrSet<int *> Val_int_ptrs;
40089a1d03eSRichard     for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),
40189a1d03eSRichard                                  E = Val_int_ptrs.end();
40289a1d03eSRichard          I != E; ++I) {
40389a1d03eSRichard       (void) *I;
40489a1d03eSRichard     }
40589a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
40689a1d03eSRichard     // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
40789a1d03eSRichard   }
40889a1d03eSRichard 
40989a1d03eSRichard   // This container uses an iterator where the dereference type is a typedef of
41089a1d03eSRichard   // a reference type. Make sure non-const auto & is still used. A failure here
41189a1d03eSRichard   // means canonical types aren't being tested.
41289a1d03eSRichard   {
41389a1d03eSRichard     TypedefDerefContainer<int> Int_ptrs;
41489a1d03eSRichard     for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),
41589a1d03eSRichard                                               E = Int_ptrs.end();
41689a1d03eSRichard          I != E; ++I) {
41789a1d03eSRichard       (void) *I;
41889a1d03eSRichard     }
41989a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
42089a1d03eSRichard     // CHECK-FIXES: for (int & Int_ptr : Int_ptrs)
42189a1d03eSRichard   }
42289a1d03eSRichard 
42389a1d03eSRichard   {
42489a1d03eSRichard     // Iterators returning an rvalue reference should disqualify the loop from
42589a1d03eSRichard     // transformation.
42689a1d03eSRichard     RValueDerefContainer<int> Container;
42789a1d03eSRichard     for (RValueDerefContainer<int>::iterator I = Container.begin(),
42889a1d03eSRichard                                              E = Container.end();
42989a1d03eSRichard          I != E; ++I) {
43089a1d03eSRichard       (void) *I;
43189a1d03eSRichard     }
43289a1d03eSRichard   }
43389a1d03eSRichard 
43489a1d03eSRichard   dependent<Val *> Dpp;
43589a1d03eSRichard   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
43689a1d03eSRichard     printf("%d\n", (**I).X);
43789a1d03eSRichard   }
43889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
43989a1d03eSRichard   // CHECK-FIXES: for (auto & I : Dpp)
44089a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", (*I).X);
44189a1d03eSRichard 
44289a1d03eSRichard   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
44389a1d03eSRichard     printf("%d\n", (*I)->X);
44489a1d03eSRichard   }
44589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
44689a1d03eSRichard   // CHECK-FIXES: for (auto & I : Dpp)
44789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
44889a1d03eSRichard }
44989a1d03eSRichard 
45089a1d03eSRichard // Tests to verify the proper use of auto where the init variable type and the
45189a1d03eSRichard // initializer type differ or are mostly the same except for const qualifiers.
45289a1d03eSRichard void different_type() {
45389a1d03eSRichard   // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
45489a1d03eSRichard   // differs from const_iterator only on the const qualification.
45589a1d03eSRichard   S Ss;
45689a1d03eSRichard   for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
45789a1d03eSRichard     printf("s has value %d\n", (*It).X);
45889a1d03eSRichard   }
45989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
46089a1d03eSRichard   // CHECK-FIXES: for (auto It : Ss)
46189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
46289a1d03eSRichard 
46389a1d03eSRichard   S *Ps;
46489a1d03eSRichard   for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
46589a1d03eSRichard     printf("s has value %d\n", (*It).X);
46689a1d03eSRichard   }
46789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
46889a1d03eSRichard   // CHECK-FIXES: for (auto P : *Ps)
46989a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
47089a1d03eSRichard 
47189a1d03eSRichard   dependent<int> V;
47289a1d03eSRichard   for (dependent<int>::const_iterator It = V.begin(), E = V.end();
47389a1d03eSRichard        It != E; ++It) {
47489a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
47589a1d03eSRichard   }
47689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
47789a1d03eSRichard   // CHECK-FIXES: for (int It : V)
47889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
47989a1d03eSRichard 
48089a1d03eSRichard   for (dependent<int>::const_iterator It(V.begin()), E = V.end();
48189a1d03eSRichard        It != E; ++It) {
48289a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
48389a1d03eSRichard   }
48489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
48589a1d03eSRichard   // CHECK-FIXES: for (int It : V)
48689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
48789a1d03eSRichard }
48889a1d03eSRichard 
48989a1d03eSRichard // Tests to ensure that an implicit 'this' is picked up as the container.
49089a1d03eSRichard // If member calls are made to 'this' within the loop, the transform becomes
49189a1d03eSRichard // risky as these calls may affect state that affects the loop.
49289a1d03eSRichard class C {
49389a1d03eSRichard public:
49489a1d03eSRichard   typedef MutableVal *iterator;
49589a1d03eSRichard   typedef const MutableVal *const_iterator;
49689a1d03eSRichard 
49789a1d03eSRichard   iterator begin();
49889a1d03eSRichard   iterator end();
49989a1d03eSRichard   const_iterator begin() const;
50089a1d03eSRichard   const_iterator end() const;
50189a1d03eSRichard 
50289a1d03eSRichard   void doSomething();
50389a1d03eSRichard   void doSomething() const;
50489a1d03eSRichard 
50589a1d03eSRichard   void doLoop() {
50689a1d03eSRichard     for (iterator I = begin(), E = end(); I != E; ++I)
50789a1d03eSRichard       (void) *I;
50889a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
50989a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
51089a1d03eSRichard 
51189a1d03eSRichard     for (iterator I = C::begin(), E = C::end(); I != E; ++I)
51289a1d03eSRichard       (void) *I;
51389a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
51489a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
51589a1d03eSRichard 
51689a1d03eSRichard     for (iterator I = begin(), E = end(); I != E; ++I) {
51789a1d03eSRichard       (void) *I;
51889a1d03eSRichard       doSomething();
51989a1d03eSRichard     }
52089a1d03eSRichard 
52189a1d03eSRichard     for (iterator I = begin(); I != end(); ++I)
52289a1d03eSRichard       (void) *I;
52389a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
52489a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
52589a1d03eSRichard 
52689a1d03eSRichard     for (iterator I = begin(); I != end(); ++I) {
52789a1d03eSRichard       (void) *I;
52889a1d03eSRichard       doSomething();
52989a1d03eSRichard     }
53089a1d03eSRichard   }
53189a1d03eSRichard 
53289a1d03eSRichard   void doLoop() const {
53389a1d03eSRichard     for (const_iterator I = begin(), E = end(); I != E; ++I)
53489a1d03eSRichard       (void) *I;
53589a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
53689a1d03eSRichard     // CHECK-FIXES: for (auto I : *this)
53789a1d03eSRichard 
53889a1d03eSRichard     for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
53989a1d03eSRichard       (void) *I;
54089a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
54189a1d03eSRichard     // CHECK-FIXES: for (auto I : *this)
54289a1d03eSRichard 
54389a1d03eSRichard     for (const_iterator I = begin(), E = end(); I != E; ++I) {
54489a1d03eSRichard       (void) *I;
54589a1d03eSRichard       doSomething();
54689a1d03eSRichard     }
54789a1d03eSRichard   }
54889a1d03eSRichard };
54989a1d03eSRichard 
55089a1d03eSRichard class C2 {
55189a1d03eSRichard public:
55289a1d03eSRichard   typedef MutableVal *iterator;
55389a1d03eSRichard 
55489a1d03eSRichard   iterator begin() const;
55589a1d03eSRichard   iterator end() const;
55689a1d03eSRichard 
55789a1d03eSRichard   void doLoop() {
55889a1d03eSRichard     // The implicit 'this' will have an Implicit cast to const C2* wrapped
55989a1d03eSRichard     // around it. Make sure the replacement still happens.
56089a1d03eSRichard     for (iterator I = begin(), E = end(); I != E; ++I)
56189a1d03eSRichard       (void) *I;
56289a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
56389a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
56489a1d03eSRichard   }
56589a1d03eSRichard };
56689a1d03eSRichard 
56789a1d03eSRichard } // namespace Iterator
56889a1d03eSRichard 
56989a1d03eSRichard namespace PseudoArray {
57089a1d03eSRichard 
57189a1d03eSRichard const int N = 6;
57289a1d03eSRichard dependent<int> V;
57389a1d03eSRichard dependent<int> *Pv;
57489a1d03eSRichard const dependent<NonTriviallyCopyable> Constv;
57589a1d03eSRichard const dependent<NonTriviallyCopyable> *Pconstv;
57689a1d03eSRichard 
57789a1d03eSRichard transparent<dependent<int>> Cv;
578*e4329520SChris Cotter dependent_derived<int> VD;
57989a1d03eSRichard 
58089a1d03eSRichard void f() {
58189a1d03eSRichard   int Sum = 0;
58289a1d03eSRichard   for (int I = 0, E = V.size(); I < E; ++I) {
58389a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
58489a1d03eSRichard     Sum += V[I] + 2;
58589a1d03eSRichard   }
58689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
58789a1d03eSRichard   // CHECK-FIXES: for (int I : V)
58889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
58989a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
59089a1d03eSRichard 
59189a1d03eSRichard   for (int I = 0, E = V.size(); I < E; ++I) {
59289a1d03eSRichard     printf("Fibonacci number is %d\n", V.at(I));
59389a1d03eSRichard     Sum += V.at(I) + 2;
59489a1d03eSRichard   }
59589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
59689a1d03eSRichard   // CHECK-FIXES: for (int I : V)
59789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
59889a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
59989a1d03eSRichard 
60089a1d03eSRichard   for (int I = 0, E = Pv->size(); I < E; ++I) {
60189a1d03eSRichard     printf("Fibonacci number is %d\n", Pv->at(I));
60289a1d03eSRichard     Sum += Pv->at(I) + 2;
60389a1d03eSRichard   }
60489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
60589a1d03eSRichard   // CHECK-FIXES: for (int I : *Pv)
60689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
60789a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
60889a1d03eSRichard 
60989a1d03eSRichard   // This test will fail if size() isn't called repeatedly, since it
61089a1d03eSRichard   // returns unsigned int, and 0 is deduced to be signed int.
61189a1d03eSRichard   // FIXME: Insert the necessary explicit conversion, or write out the types
61289a1d03eSRichard   // explicitly.
61389a1d03eSRichard   for (int I = 0; I < Pv->size(); ++I) {
61489a1d03eSRichard     printf("Fibonacci number is %d\n", (*Pv).at(I));
61589a1d03eSRichard     Sum += (*Pv)[I] + 2;
61689a1d03eSRichard   }
61789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
61889a1d03eSRichard   // CHECK-FIXES: for (int I : *Pv)
61989a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
62089a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
62189a1d03eSRichard 
62289a1d03eSRichard   for (int I = 0; I < Cv->size(); ++I) {
62389a1d03eSRichard     printf("Fibonacci number is %d\n", Cv->at(I));
62489a1d03eSRichard     Sum += Cv->at(I) + 2;
62589a1d03eSRichard   }
62689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
62789a1d03eSRichard   // CHECK-FIXES: for (int I : *Cv)
62889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
62989a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
63089a1d03eSRichard 
63189a1d03eSRichard   for (int I = 0, E = V.size(); E > I; ++I) {
63289a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
63389a1d03eSRichard     Sum += V[I] + 2;
63489a1d03eSRichard   }
63589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
63689a1d03eSRichard   // CHECK-FIXES: for (int I : V)
63789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
63889a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
63989a1d03eSRichard 
64089a1d03eSRichard   for (int I = 0, E = V.size(); I != E; ++I) {
64189a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
64289a1d03eSRichard     Sum += V[I] + 2;
64389a1d03eSRichard   }
64489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
64589a1d03eSRichard   // CHECK-FIXES: for (int I : V)
64689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
64789a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
64889a1d03eSRichard 
64989a1d03eSRichard   for (int I = 0, E = V.size(); E != I; ++I) {
65089a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
65189a1d03eSRichard     Sum += V[I] + 2;
65289a1d03eSRichard   }
65389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
65489a1d03eSRichard   // CHECK-FIXES: for (int I : V)
65589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
65689a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
657*e4329520SChris Cotter 
658*e4329520SChris Cotter   for (int I = 0, E = VD.size(); E != I; ++I) {
659*e4329520SChris Cotter     printf("Fibonacci number is %d\n", VD[I]);
660*e4329520SChris Cotter     Sum += VD[I] + 2;
661*e4329520SChris Cotter   }
662*e4329520SChris Cotter   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
663*e4329520SChris Cotter   // CHECK-FIXES: for (int I : VD)
664*e4329520SChris Cotter   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
665*e4329520SChris Cotter   // CHECK-FIXES-NEXT: Sum += I + 2;
66689a1d03eSRichard }
66789a1d03eSRichard 
66889a1d03eSRichard // Ensure that 'const auto &' is used with containers of non-trivial types.
66989a1d03eSRichard void constness() {
67089a1d03eSRichard   int Sum = 0;
67189a1d03eSRichard   for (int I = 0, E = Constv.size(); I < E; ++I) {
67289a1d03eSRichard     printf("Fibonacci number is %d\n", Constv[I].X);
67389a1d03eSRichard     Sum += Constv[I].X + 2;
67489a1d03eSRichard   }
67589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
67689a1d03eSRichard   // CHECK-FIXES: for (const auto & I : Constv)
67789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
67889a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
67989a1d03eSRichard 
68089a1d03eSRichard   for (int I = 0, E = Constv.size(); I < E; ++I) {
68189a1d03eSRichard     printf("Fibonacci number is %d\n", Constv.at(I).X);
68289a1d03eSRichard     Sum += Constv.at(I).X + 2;
68389a1d03eSRichard   }
68489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
68589a1d03eSRichard   // CHECK-FIXES: for (const auto & I : Constv)
68689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
68789a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
68889a1d03eSRichard 
68989a1d03eSRichard   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
69089a1d03eSRichard     printf("Fibonacci number is %d\n", Pconstv->at(I).X);
69189a1d03eSRichard     Sum += Pconstv->at(I).X + 2;
69289a1d03eSRichard   }
69389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
69489a1d03eSRichard   // CHECK-FIXES: for (const auto & I : *Pconstv)
69589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
69689a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
69789a1d03eSRichard 
69889a1d03eSRichard   // This test will fail if size() isn't called repeatedly, since it
69989a1d03eSRichard   // returns unsigned int, and 0 is deduced to be signed int.
70089a1d03eSRichard   // FIXME: Insert the necessary explicit conversion, or write out the types
70189a1d03eSRichard   // explicitly.
70289a1d03eSRichard   for (int I = 0; I < Pconstv->size(); ++I) {
70389a1d03eSRichard     printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
70489a1d03eSRichard     Sum += (*Pconstv)[I].X + 2;
70589a1d03eSRichard   }
70689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
70789a1d03eSRichard   // CHECK-FIXES: for (const auto & I : *Pconstv)
70889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
70989a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
71089a1d03eSRichard }
71189a1d03eSRichard 
71289a1d03eSRichard void constRef(const dependent<int>& ConstVRef) {
71389a1d03eSRichard   int sum = 0;
71489a1d03eSRichard   // FIXME: This does not work with size_t (probably due to the implementation
71589a1d03eSRichard   // of dependent); make dependent work exactly like a std container type.
71689a1d03eSRichard   for (int I = 0; I < ConstVRef.size(); ++I) {
71789a1d03eSRichard     sum += ConstVRef[I];
71889a1d03eSRichard   }
71989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
72089a1d03eSRichard   // CHECK-FIXES: for (int I : ConstVRef)
72189a1d03eSRichard   // CHECK-FIXES-NEXT: sum += I;
72289a1d03eSRichard 
72389a1d03eSRichard   for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
72489a1d03eSRichard     sum += *I;
72589a1d03eSRichard   }
72689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
72789a1d03eSRichard   // CHECK-FIXES: for (int I : ConstVRef)
72889a1d03eSRichard   // CHECK-FIXES-NEXT: sum += I;
72989a1d03eSRichard }
73089a1d03eSRichard 
73189a1d03eSRichard // Check for loops that don't mention containers.
73289a1d03eSRichard void noContainer() {
73389a1d03eSRichard   for (auto I = 0; I < V.size(); ++I) {
73489a1d03eSRichard   }
73589a1d03eSRichard 
73689a1d03eSRichard   for (auto I = 0; I < V.size(); ++I)
73789a1d03eSRichard     ;
73889a1d03eSRichard }
73989a1d03eSRichard 
74089a1d03eSRichard struct NoBeginEnd {
74189a1d03eSRichard   unsigned size() const;
74289a1d03eSRichard   unsigned& operator[](int);
74389a1d03eSRichard   const unsigned& operator[](int) const;
74489a1d03eSRichard };
74589a1d03eSRichard 
74689a1d03eSRichard struct NoConstBeginEnd {
74789a1d03eSRichard   NoConstBeginEnd();
74889a1d03eSRichard   unsigned size() const;
74989a1d03eSRichard   unsigned* begin();
75089a1d03eSRichard   unsigned* end();
75189a1d03eSRichard   unsigned& operator[](int);
75289a1d03eSRichard   const unsigned& operator[](int) const;
75389a1d03eSRichard };
75489a1d03eSRichard 
75589a1d03eSRichard struct ConstBeginEnd {
75689a1d03eSRichard   ConstBeginEnd();
75789a1d03eSRichard   unsigned size() const;
75889a1d03eSRichard   unsigned* begin() const;
75989a1d03eSRichard   unsigned* end() const;
76089a1d03eSRichard   unsigned& operator[](int);
76189a1d03eSRichard   const unsigned& operator[](int) const;
76289a1d03eSRichard };
76389a1d03eSRichard 
76489a1d03eSRichard // Shouldn't transform pseudo-array uses if the container doesn't provide
76589a1d03eSRichard // begin() and end() of the right const-ness.
76689a1d03eSRichard void NoBeginEndTest() {
76789a1d03eSRichard   NoBeginEnd NBE;
76889a1d03eSRichard   for (unsigned I = 0, E = NBE.size(); I < E; ++I)
76989a1d03eSRichard     printf("%d\n", NBE[I]);
77089a1d03eSRichard 
77189a1d03eSRichard   const NoConstBeginEnd Const_NCBE;
77289a1d03eSRichard   for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
77389a1d03eSRichard     printf("%d\n", Const_NCBE[I]);
77489a1d03eSRichard 
77589a1d03eSRichard   ConstBeginEnd CBE;
77689a1d03eSRichard   for (unsigned I = 0, E = CBE.size(); I < E; ++I)
77789a1d03eSRichard     printf("%d\n", CBE[I]);
77889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
77989a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : CBE)
78089a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
78189a1d03eSRichard 
78289a1d03eSRichard   const ConstBeginEnd Const_CBE;
78389a1d03eSRichard   for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
78489a1d03eSRichard     printf("%d\n", Const_CBE[I]);
78589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
78689a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : Const_CBE)
78789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
78889a1d03eSRichard }
78989a1d03eSRichard 
79089a1d03eSRichard struct DerefByValue {
79189a1d03eSRichard   DerefByValue();
79289a1d03eSRichard   struct iter { unsigned operator*(); };
79389a1d03eSRichard   unsigned size() const;
79489a1d03eSRichard   iter begin();
79589a1d03eSRichard   iter end();
79689a1d03eSRichard   unsigned operator[](int);
79789a1d03eSRichard };
79889a1d03eSRichard 
79989a1d03eSRichard void derefByValueTest() {
80089a1d03eSRichard   DerefByValue DBV;
80189a1d03eSRichard   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
80289a1d03eSRichard     printf("%d\n", DBV[I]);
80389a1d03eSRichard   }
80489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
80589a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : DBV)
80689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
80789a1d03eSRichard 
80889a1d03eSRichard   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
80989a1d03eSRichard     auto f = [DBV, I]() {};
81089a1d03eSRichard     printf("%d\n", DBV[I]);
81189a1d03eSRichard   }
81289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
81389a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : DBV)
81489a1d03eSRichard   // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
81589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
81689a1d03eSRichard }
81789a1d03eSRichard 
81889a1d03eSRichard void fundamentalTypesTest() {
81989a1d03eSRichard   const int N = 10;
82089a1d03eSRichard   bool Bools[N];
82189a1d03eSRichard   for (int i = 0; i < N; ++i)
82289a1d03eSRichard     printf("%d", Bools[i]);
82389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
82489a1d03eSRichard   // CHECK-FIXES: for (bool Bool : Bools)
82589a1d03eSRichard 
82689a1d03eSRichard   int Ints[N];
82789a1d03eSRichard   unsigned short int Shorts[N];
82889a1d03eSRichard   for (int i = 0; i < N; ++i)
82989a1d03eSRichard     printf("%d", Shorts[i]);
83089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
83189a1d03eSRichard   // CHECK-FIXES: for (unsigned short Short : Shorts)
83289a1d03eSRichard 
83389a1d03eSRichard   signed long Longs[N];
83489a1d03eSRichard   for (int i = 0; i < N; ++i)
83589a1d03eSRichard     printf("%d", Longs[i]);
83689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
83789a1d03eSRichard   // CHECK-FIXES: for (long Long : Longs)
83889a1d03eSRichard 
83989a1d03eSRichard   long long int LongLongs[N];
84089a1d03eSRichard   for (int i = 0; i < N; ++i)
84189a1d03eSRichard     printf("%d", LongLongs[i]);
84289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
84389a1d03eSRichard   // CHECK-FIXES: for (long long LongLong : LongLongs)
84489a1d03eSRichard 
84589a1d03eSRichard   char Chars[N];
84689a1d03eSRichard   for (int i = 0; i < N; ++i)
84789a1d03eSRichard     printf("%d", Chars[i]);
84889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
84989a1d03eSRichard   // CHECK-FIXES: for (char Char : Chars)
85089a1d03eSRichard 
85189a1d03eSRichard   wchar_t WChars[N];
85289a1d03eSRichard   for (int i = 0; i < N; ++i)
85389a1d03eSRichard     printf("%d", WChars[i]);
85489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
85589a1d03eSRichard   // CHECK-FIXES: for (wchar_t WChar : WChars)
85689a1d03eSRichard 
85789a1d03eSRichard   float Floats[N];
85889a1d03eSRichard   for (int i = 0; i < N; ++i)
85989a1d03eSRichard     printf("%d", Floats[i]);
86089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
86189a1d03eSRichard   // CHECK-FIXES: for (float Float : Floats)
86289a1d03eSRichard 
86389a1d03eSRichard   double Doubles[N];
86489a1d03eSRichard   for (int i = 0; i < N; ++i)
86589a1d03eSRichard     printf("%d", Doubles[i]);
86689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
86789a1d03eSRichard   // CHECK-FIXES: for (double Double : Doubles)
86889a1d03eSRichard }
86989a1d03eSRichard 
87089a1d03eSRichard } // namespace PseudoArray
871