xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp (revision e984d11d7257343da366d9fa03749a43a6d6af72)
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 
915e83b265SDanny Mösch   int Matrix[N][12];
925e83b265SDanny Mösch   unsigned size = 0;
935e83b265SDanny Mösch   for (int I = 0; I < N; ++I) {
945e83b265SDanny Mösch       size += sizeof(Matrix[I]);
955e83b265SDanny Mösch       size += sizeof Matrix[I];
965e83b265SDanny Mösch       size += sizeof((Matrix[I]));
975e83b265SDanny Mösch   }
985e83b265SDanny Mösch   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
995e83b265SDanny Mösch   // CHECK-FIXES: for (auto & I : Matrix)
1005e83b265SDanny Mösch   // CHECK-FIXES-NEXT: size += sizeof(I);
1015e83b265SDanny Mösch   // CHECK-FIXES-NEXT: size += sizeof I;
1025e83b265SDanny Mösch   // CHECK-FIXES-NEXT: size += sizeof(I);
1035e83b265SDanny Mösch 
10489a1d03eSRichard   Val Teas[N];
10589a1d03eSRichard   for (int I = 0; I < N; ++I) {
10689a1d03eSRichard     Teas[I].g();
10789a1d03eSRichard   }
10889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
10989a1d03eSRichard   // CHECK-FIXES: for (auto & Tea : Teas)
11089a1d03eSRichard   // CHECK-FIXES-NEXT: Tea.g();
11189a1d03eSRichard 
11289a1d03eSRichard   for (int I = 0; N > I; ++I) {
11389a1d03eSRichard     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
11489a1d03eSRichard     Sum += Arr[I] + 2;
11589a1d03eSRichard   }
11689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
11789a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
11889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
11989a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
12089a1d03eSRichard 
12189a1d03eSRichard   for (int I = 0; N != I; ++I) {
12289a1d03eSRichard     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
12389a1d03eSRichard     Sum += Arr[I] + 2;
12489a1d03eSRichard   }
12589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
12689a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
12789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
12889a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
12989a1d03eSRichard 
13089a1d03eSRichard   for (int I = 0; I != N; ++I) {
13189a1d03eSRichard     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
13289a1d03eSRichard     Sum += Arr[I] + 2;
13389a1d03eSRichard   }
13489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
13589a1d03eSRichard   // CHECK-FIXES: for (int & I : Arr)
13689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
13789a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
13889a1d03eSRichard }
13989a1d03eSRichard 
14089a1d03eSRichard const int *constArray() {
14189a1d03eSRichard   for (int I = 0; I < N; ++I) {
14289a1d03eSRichard     printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
14389a1d03eSRichard   }
14489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
14589a1d03eSRichard   // CHECK-FIXES: for (int I : ConstArr)
14689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I);
14789a1d03eSRichard 
14889a1d03eSRichard   const NonTriviallyCopyable NonCopy[N]{};
14989a1d03eSRichard   for (int I = 0; I < N; ++I) {
15089a1d03eSRichard     printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
15189a1d03eSRichard   }
15289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
15389a1d03eSRichard   // CHECK-FIXES: for (const auto & I : NonCopy)
15489a1d03eSRichard   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
15589a1d03eSRichard 
15689a1d03eSRichard   const TriviallyCopyableButBig Big[N]{};
15789a1d03eSRichard   for (int I = 0; I < N; ++I) {
15889a1d03eSRichard     printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X);
15989a1d03eSRichard   }
16089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
16189a1d03eSRichard   // CHECK-FIXES: for (const auto & I : Big)
16289a1d03eSRichard   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
16389a1d03eSRichard 
16489a1d03eSRichard   bool Something = false;
16589a1d03eSRichard   for (int I = 0; I < N; ++I) {
16689a1d03eSRichard     if (Something)
16789a1d03eSRichard       return &ConstArr[I];
16889a1d03eSRichard   }
16989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
17089a1d03eSRichard   // CHECK-FIXES: for (const int & I : ConstArr)
17189a1d03eSRichard   // CHECK-FIXES-NEXT: if (Something)
17289a1d03eSRichard   // CHECK-FIXES-NEXT: return &I;
17389a1d03eSRichard }
17489a1d03eSRichard 
17589a1d03eSRichard struct HasArr {
17689a1d03eSRichard   int Arr[N];
17789a1d03eSRichard   Val ValArr[N];
17889a1d03eSRichard   void implicitThis() {
17989a1d03eSRichard     for (int I = 0; I < N; ++I) {
18089a1d03eSRichard       printf("%d", Arr[I]);
18189a1d03eSRichard     }
18289a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
18389a1d03eSRichard     // CHECK-FIXES: for (int I : Arr)
18489a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I);
18589a1d03eSRichard 
18689a1d03eSRichard     for (int I = 0; I < N; ++I) {
18789a1d03eSRichard       printf("%d", ValArr[I].X);
18889a1d03eSRichard     }
18989a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
19089a1d03eSRichard     // CHECK-FIXES: for (auto & I : ValArr)
19189a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I.X);
19289a1d03eSRichard   }
19389a1d03eSRichard 
19489a1d03eSRichard   void explicitThis() {
19589a1d03eSRichard     for (int I = 0; I < N; ++I) {
19689a1d03eSRichard       printf("%d", this->Arr[I]);
19789a1d03eSRichard     }
19889a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
19989a1d03eSRichard     // CHECK-FIXES: for (int I : this->Arr)
20089a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I);
20189a1d03eSRichard 
20289a1d03eSRichard     for (int I = 0; I < N; ++I) {
20389a1d03eSRichard       printf("%d", this->ValArr[I].X);
20489a1d03eSRichard     }
20589a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
20689a1d03eSRichard     // CHECK-FIXES: for (auto & I : this->ValArr)
20789a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I.X);
20889a1d03eSRichard   }
20989a1d03eSRichard };
21089a1d03eSRichard 
21189a1d03eSRichard struct HasIndirectArr {
21289a1d03eSRichard   HasArr HA;
21389a1d03eSRichard   void implicitThis() {
21489a1d03eSRichard     for (int I = 0; I < N; ++I) {
21589a1d03eSRichard       printf("%d", HA.Arr[I]);
21689a1d03eSRichard     }
21789a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
21889a1d03eSRichard     // CHECK-FIXES: for (int I : HA.Arr)
21989a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I);
22089a1d03eSRichard 
22189a1d03eSRichard     for (int I = 0; I < N; ++I) {
22289a1d03eSRichard       printf("%d", HA.ValArr[I].X);
22389a1d03eSRichard     }
22489a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
22589a1d03eSRichard     // CHECK-FIXES: for (auto & I : HA.ValArr)
22689a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I.X);
22789a1d03eSRichard   }
22889a1d03eSRichard 
22989a1d03eSRichard   void explicitThis() {
23089a1d03eSRichard     for (int I = 0; I < N; ++I) {
23189a1d03eSRichard       printf("%d", this->HA.Arr[I]);
23289a1d03eSRichard     }
23389a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
23489a1d03eSRichard     // CHECK-FIXES: for (int I : this->HA.Arr)
23589a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I);
23689a1d03eSRichard 
23789a1d03eSRichard     for (int I = 0; I < N; ++I) {
23889a1d03eSRichard       printf("%d", this->HA.ValArr[I].X);
23989a1d03eSRichard     }
24089a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
24189a1d03eSRichard     // CHECK-FIXES: for (auto & I : this->HA.ValArr)
24289a1d03eSRichard     // CHECK-FIXES-NEXT: printf("%d", I.X);
24389a1d03eSRichard   }
24489a1d03eSRichard };
24589a1d03eSRichard 
24689a1d03eSRichard // Loops whose bounds are value-dependent should not be converted.
24789a1d03eSRichard template <int N>
24889a1d03eSRichard void dependentExprBound() {
24989a1d03eSRichard   for (int I = 0; I < N; ++I)
25089a1d03eSRichard     Arr[I] = 0;
25189a1d03eSRichard }
25289a1d03eSRichard template void dependentExprBound<20>();
25389a1d03eSRichard 
25489a1d03eSRichard void memberFunctionPointer() {
25589a1d03eSRichard   Val V;
25689a1d03eSRichard   void (Val::*mfpArr[N])(void) = {&Val::g};
25789a1d03eSRichard   for (int I = 0; I < N; ++I)
25889a1d03eSRichard     (V.*mfpArr[I])();
25989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
26089a1d03eSRichard   // CHECK-FIXES: for (auto & I : mfpArr)
26189a1d03eSRichard   // CHECK-FIXES-NEXT: (V.*I)();
26289a1d03eSRichard 
26389a1d03eSRichard   struct Foo {
26489a1d03eSRichard     int (Val::*f)();
26589a1d03eSRichard   } Foo[N];
26689a1d03eSRichard 
26789a1d03eSRichard   for (int I = 0; I < N; ++I)
26889a1d03eSRichard     int R = (V.*(Foo[I].f))();
26989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
27089a1d03eSRichard   // CHECK-FIXES: for (auto & I : Foo)
27189a1d03eSRichard   // CHECK-FIXES-NEXT: int R = (V.*(I.f))();
27289a1d03eSRichard 
27389a1d03eSRichard }
27489a1d03eSRichard 
27589a1d03eSRichard } // namespace Array
27689a1d03eSRichard 
27789a1d03eSRichard namespace Iterator {
27889a1d03eSRichard 
27989a1d03eSRichard void f() {
28089a1d03eSRichard   /// begin()/end() - based for loops here:
28189a1d03eSRichard   T Tt;
28289a1d03eSRichard   for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) {
28389a1d03eSRichard     printf("I found %d\n", *It);
28489a1d03eSRichard   }
28589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
28689a1d03eSRichard   // CHECK-FIXES: for (int & It : Tt)
28789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
28889a1d03eSRichard 
28989a1d03eSRichard   // Do not crash because of Qq.begin() converting. Q::iterator converts with a
29089a1d03eSRichard   // conversion operator, which has no name, to Q::const_iterator.
29189a1d03eSRichard   Q Qq;
29289a1d03eSRichard   for (Q::const_iterator It = Qq.begin(), E = Qq.end(); It != E; ++It) {
29389a1d03eSRichard     printf("I found %d\n", *It);
29489a1d03eSRichard   }
29589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
29689a1d03eSRichard   // CHECK-FIXES: for (int & It : Qq)
29789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
29889a1d03eSRichard 
29989a1d03eSRichard   T *Pt;
30089a1d03eSRichard   for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
30189a1d03eSRichard     printf("I found %d\n", *It);
30289a1d03eSRichard   }
30389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
30489a1d03eSRichard   // CHECK-FIXES: for (int & It : *Pt)
30589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
30689a1d03eSRichard 
30789a1d03eSRichard   S Ss;
30889a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
30989a1d03eSRichard     printf("s has value %d\n", (*It).X);
31089a1d03eSRichard   }
31189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
31289a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
31389a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
31489a1d03eSRichard 
31589a1d03eSRichard   S *Ps;
31689a1d03eSRichard   for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
31789a1d03eSRichard     printf("s has value %d\n", (*It).X);
31889a1d03eSRichard   }
31989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
32089a1d03eSRichard   // CHECK-FIXES: for (auto & P : *Ps)
32189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
32289a1d03eSRichard 
32389a1d03eSRichard   for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
32489a1d03eSRichard     printf("s has value %d\n", (*It).X);
32589a1d03eSRichard   }
32689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
32789a1d03eSRichard   // CHECK-FIXES: for (auto It : Ss)
32889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
32989a1d03eSRichard 
33089a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
33189a1d03eSRichard     printf("s has value %d\n", It->X);
33289a1d03eSRichard   }
33389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
33489a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
33589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
33689a1d03eSRichard 
33789a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
33889a1d03eSRichard     It->X = 3;
33989a1d03eSRichard   }
34089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
34189a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
34289a1d03eSRichard   // CHECK-FIXES-NEXT: It.X = 3;
34389a1d03eSRichard 
34489a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
34589a1d03eSRichard     (*It).X = 3;
34689a1d03eSRichard   }
34789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
34889a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
34989a1d03eSRichard   // CHECK-FIXES-NEXT: It.X = 3;
35089a1d03eSRichard 
35189a1d03eSRichard   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
35289a1d03eSRichard     It->nonConstFun(4, 5);
35389a1d03eSRichard   }
35489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
35589a1d03eSRichard   // CHECK-FIXES: for (auto & It : Ss)
35689a1d03eSRichard   // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
35789a1d03eSRichard 
35889a1d03eSRichard   U Uu;
35989a1d03eSRichard   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
36089a1d03eSRichard     printf("s has value %d\n", It->X);
36189a1d03eSRichard   }
36289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
36389a1d03eSRichard   // CHECK-FIXES: for (auto & It : Uu)
36489a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
36589a1d03eSRichard 
36689a1d03eSRichard   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
36789a1d03eSRichard     printf("s has value %d\n", (*It).X);
36889a1d03eSRichard   }
36989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
37089a1d03eSRichard   // CHECK-FIXES: for (auto & It : Uu)
37189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
37289a1d03eSRichard 
37389a1d03eSRichard   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
37489a1d03eSRichard     Val* a = It.operator->();
37589a1d03eSRichard   }
37689a1d03eSRichard 
37789a1d03eSRichard   U::iterator A;
37889a1d03eSRichard   for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)
37989a1d03eSRichard     int K = A->X + I->X;
38089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
38189a1d03eSRichard   // CHECK-FIXES: for (auto & I : Uu)
38289a1d03eSRichard   // CHECK-FIXES-NEXT: int K = A->X + I.X;
38389a1d03eSRichard 
38489a1d03eSRichard   dependent<int> V;
38589a1d03eSRichard   for (dependent<int>::iterator It = V.begin(), E = V.end();
38689a1d03eSRichard        It != E; ++It) {
38789a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
38889a1d03eSRichard   }
38989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
39089a1d03eSRichard   // CHECK-FIXES: for (int & It : V)
39189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
39289a1d03eSRichard 
39389a1d03eSRichard   for (dependent<int>::iterator It(V.begin()), E = V.end();
39489a1d03eSRichard        It != E; ++It) {
39589a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
39689a1d03eSRichard   }
39789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
39889a1d03eSRichard   // CHECK-FIXES: for (int & It : V)
39989a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
40089a1d03eSRichard 
40189a1d03eSRichard   doublyDependent<int, int> Intmap;
40289a1d03eSRichard   for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();
40389a1d03eSRichard        It != E; ++It) {
40489a1d03eSRichard     printf("Intmap[%d] = %d", It->first, It->second);
40589a1d03eSRichard   }
40689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
40789a1d03eSRichard   // CHECK-FIXES: for (auto & It : Intmap)
40889a1d03eSRichard   // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);
40989a1d03eSRichard 
41089a1d03eSRichard   // PtrSet's iterator dereferences by value so auto & can't be used.
41189a1d03eSRichard   {
41289a1d03eSRichard     PtrSet<int *> Val_int_ptrs;
41389a1d03eSRichard     for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),
41489a1d03eSRichard                                  E = Val_int_ptrs.end();
41589a1d03eSRichard          I != E; ++I) {
41689a1d03eSRichard       (void) *I;
41789a1d03eSRichard     }
41889a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
41989a1d03eSRichard     // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
42089a1d03eSRichard   }
42189a1d03eSRichard 
42289a1d03eSRichard   // This container uses an iterator where the dereference type is a typedef of
42389a1d03eSRichard   // a reference type. Make sure non-const auto & is still used. A failure here
42489a1d03eSRichard   // means canonical types aren't being tested.
42589a1d03eSRichard   {
42689a1d03eSRichard     TypedefDerefContainer<int> Int_ptrs;
42789a1d03eSRichard     for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),
42889a1d03eSRichard                                               E = Int_ptrs.end();
42989a1d03eSRichard          I != E; ++I) {
43089a1d03eSRichard       (void) *I;
43189a1d03eSRichard     }
43289a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
43389a1d03eSRichard     // CHECK-FIXES: for (int & Int_ptr : Int_ptrs)
43489a1d03eSRichard   }
43589a1d03eSRichard 
43689a1d03eSRichard   {
43789a1d03eSRichard     // Iterators returning an rvalue reference should disqualify the loop from
43889a1d03eSRichard     // transformation.
43989a1d03eSRichard     RValueDerefContainer<int> Container;
44089a1d03eSRichard     for (RValueDerefContainer<int>::iterator I = Container.begin(),
44189a1d03eSRichard                                              E = Container.end();
44289a1d03eSRichard          I != E; ++I) {
44389a1d03eSRichard       (void) *I;
44489a1d03eSRichard     }
44589a1d03eSRichard   }
44689a1d03eSRichard 
44789a1d03eSRichard   dependent<Val *> Dpp;
44889a1d03eSRichard   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
44989a1d03eSRichard     printf("%d\n", (**I).X);
45089a1d03eSRichard   }
45189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
45289a1d03eSRichard   // CHECK-FIXES: for (auto & I : Dpp)
45389a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", (*I).X);
45489a1d03eSRichard 
45589a1d03eSRichard   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
45689a1d03eSRichard     printf("%d\n", (*I)->X);
45789a1d03eSRichard   }
45889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
45989a1d03eSRichard   // CHECK-FIXES: for (auto & I : Dpp)
46089a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
4616a1f8ef8SChris Cotter 
4626a1f8ef8SChris Cotter   for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
4636a1f8ef8SChris Cotter     printf("s0 has value %d\n", (*It).X);
4646a1f8ef8SChris Cotter   }
4656a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
4666a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & It : Ss)
4676a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
4686a1f8ef8SChris Cotter 
4696a1f8ef8SChris Cotter   for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
4706a1f8ef8SChris Cotter     printf("s1 has value %d\n", (*It).X);
4716a1f8ef8SChris Cotter   }
4726a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
4736a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & It : Ss)
4746a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
4756a1f8ef8SChris Cotter 
4766a1f8ef8SChris Cotter   for (S::iterator It = begin(*Ps), E = end(*Ps); It != E; ++It) {
4776a1f8ef8SChris Cotter     printf("s2 has value %d\n", (*It).X);
4786a1f8ef8SChris Cotter   }
4796a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
4806a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & It : *Ps)
4816a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s2 has value %d\n", It.X);
4826a1f8ef8SChris Cotter 
4836a1f8ef8SChris Cotter   for (S::iterator It = begin(*Ps); It != end(*Ps); ++It) {
4846a1f8ef8SChris Cotter     printf("s3 has value %d\n", (*It).X);
4856a1f8ef8SChris Cotter   }
4866a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
4876a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & It : *Ps)
4886a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s3 has value %d\n", It.X);
4896a1f8ef8SChris Cotter 
4906a1f8ef8SChris Cotter   for (S::const_iterator It = cbegin(Ss), E = cend(Ss); It != E; ++It) {
4916a1f8ef8SChris Cotter     printf("s4 has value %d\n", (*It).X);
4926a1f8ef8SChris Cotter   }
4936a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
4946a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto It : Ss)
4956a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s4 has value %d\n", It.X);
49689a1d03eSRichard }
49789a1d03eSRichard 
49889a1d03eSRichard // Tests to verify the proper use of auto where the init variable type and the
49989a1d03eSRichard // initializer type differ or are mostly the same except for const qualifiers.
50089a1d03eSRichard void different_type() {
50189a1d03eSRichard   // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
50289a1d03eSRichard   // differs from const_iterator only on the const qualification.
50389a1d03eSRichard   S Ss;
50489a1d03eSRichard   for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
50589a1d03eSRichard     printf("s has value %d\n", (*It).X);
50689a1d03eSRichard   }
50789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
50889a1d03eSRichard   // CHECK-FIXES: for (auto It : Ss)
50989a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
51089a1d03eSRichard 
51189a1d03eSRichard   S *Ps;
51289a1d03eSRichard   for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
51389a1d03eSRichard     printf("s has value %d\n", (*It).X);
51489a1d03eSRichard   }
51589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
51689a1d03eSRichard   // CHECK-FIXES: for (auto P : *Ps)
51789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
51889a1d03eSRichard 
51989a1d03eSRichard   dependent<int> V;
52089a1d03eSRichard   for (dependent<int>::const_iterator It = V.begin(), E = V.end();
52189a1d03eSRichard        It != E; ++It) {
52289a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
52389a1d03eSRichard   }
52489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
52589a1d03eSRichard   // CHECK-FIXES: for (int It : V)
52689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
52789a1d03eSRichard 
52889a1d03eSRichard   for (dependent<int>::const_iterator It(V.begin()), E = V.end();
52989a1d03eSRichard        It != E; ++It) {
53089a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
53189a1d03eSRichard   }
53289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
53389a1d03eSRichard   // CHECK-FIXES: for (int It : V)
53489a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
53589a1d03eSRichard }
53689a1d03eSRichard 
53789a1d03eSRichard // Tests to ensure that an implicit 'this' is picked up as the container.
53889a1d03eSRichard // If member calls are made to 'this' within the loop, the transform becomes
53989a1d03eSRichard // risky as these calls may affect state that affects the loop.
54089a1d03eSRichard class C {
54189a1d03eSRichard public:
54289a1d03eSRichard   typedef MutableVal *iterator;
54389a1d03eSRichard   typedef const MutableVal *const_iterator;
54489a1d03eSRichard 
54589a1d03eSRichard   iterator begin();
54689a1d03eSRichard   iterator end();
54789a1d03eSRichard   const_iterator begin() const;
54889a1d03eSRichard   const_iterator end() const;
54989a1d03eSRichard 
55089a1d03eSRichard   void doSomething();
55189a1d03eSRichard   void doSomething() const;
55289a1d03eSRichard 
55389a1d03eSRichard   void doLoop() {
55489a1d03eSRichard     for (iterator I = begin(), E = end(); I != E; ++I)
55589a1d03eSRichard       (void) *I;
55689a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
55789a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
55889a1d03eSRichard 
55989a1d03eSRichard     for (iterator I = C::begin(), E = C::end(); I != E; ++I)
56089a1d03eSRichard       (void) *I;
56189a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
56289a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
56389a1d03eSRichard 
56489a1d03eSRichard     for (iterator I = begin(), E = end(); I != E; ++I) {
56589a1d03eSRichard       (void) *I;
56689a1d03eSRichard       doSomething();
56789a1d03eSRichard     }
56889a1d03eSRichard 
56989a1d03eSRichard     for (iterator I = begin(); I != end(); ++I)
57089a1d03eSRichard       (void) *I;
57189a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
57289a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
57389a1d03eSRichard 
57489a1d03eSRichard     for (iterator I = begin(); I != end(); ++I) {
57589a1d03eSRichard       (void) *I;
57689a1d03eSRichard       doSomething();
57789a1d03eSRichard     }
57889a1d03eSRichard   }
57989a1d03eSRichard 
58089a1d03eSRichard   void doLoop() const {
58189a1d03eSRichard     for (const_iterator I = begin(), E = end(); I != E; ++I)
58289a1d03eSRichard       (void) *I;
58389a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
58489a1d03eSRichard     // CHECK-FIXES: for (auto I : *this)
58589a1d03eSRichard 
58689a1d03eSRichard     for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
58789a1d03eSRichard       (void) *I;
58889a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
58989a1d03eSRichard     // CHECK-FIXES: for (auto I : *this)
59089a1d03eSRichard 
59189a1d03eSRichard     for (const_iterator I = begin(), E = end(); I != E; ++I) {
59289a1d03eSRichard       (void) *I;
59389a1d03eSRichard       doSomething();
59489a1d03eSRichard     }
59589a1d03eSRichard   }
59689a1d03eSRichard };
59789a1d03eSRichard 
59889a1d03eSRichard class C2 {
59989a1d03eSRichard public:
60089a1d03eSRichard   typedef MutableVal *iterator;
60189a1d03eSRichard 
60289a1d03eSRichard   iterator begin() const;
60389a1d03eSRichard   iterator end() const;
60489a1d03eSRichard 
60589a1d03eSRichard   void doLoop() {
60689a1d03eSRichard     // The implicit 'this' will have an Implicit cast to const C2* wrapped
60789a1d03eSRichard     // around it. Make sure the replacement still happens.
60889a1d03eSRichard     for (iterator I = begin(), E = end(); I != E; ++I)
60989a1d03eSRichard       (void) *I;
61089a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
61189a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
61289a1d03eSRichard   }
61389a1d03eSRichard };
61489a1d03eSRichard 
61589a1d03eSRichard } // namespace Iterator
61689a1d03eSRichard 
61789a1d03eSRichard namespace PseudoArray {
61889a1d03eSRichard 
61989a1d03eSRichard const int N = 6;
62089a1d03eSRichard dependent<int> V;
62189a1d03eSRichard dependent<int> *Pv;
62289a1d03eSRichard const dependent<NonTriviallyCopyable> Constv;
62389a1d03eSRichard const dependent<NonTriviallyCopyable> *Pconstv;
62489a1d03eSRichard 
62589a1d03eSRichard transparent<dependent<int>> Cv;
626e4329520SChris Cotter dependent_derived<int> VD;
62789a1d03eSRichard 
62889a1d03eSRichard void f() {
62989a1d03eSRichard   int Sum = 0;
63089a1d03eSRichard   for (int I = 0, E = V.size(); I < E; ++I) {
63189a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
63289a1d03eSRichard     Sum += V[I] + 2;
63389a1d03eSRichard   }
63489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
63589a1d03eSRichard   // CHECK-FIXES: for (int I : V)
63689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
63789a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
63889a1d03eSRichard 
63989a1d03eSRichard   for (int I = 0, E = V.size(); I < E; ++I) {
64089a1d03eSRichard     printf("Fibonacci number is %d\n", V.at(I));
64189a1d03eSRichard     Sum += V.at(I) + 2;
64289a1d03eSRichard   }
64389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
64489a1d03eSRichard   // CHECK-FIXES: for (int I : V)
64589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
64689a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
64789a1d03eSRichard 
64889a1d03eSRichard   for (int I = 0, E = Pv->size(); I < E; ++I) {
64989a1d03eSRichard     printf("Fibonacci number is %d\n", Pv->at(I));
65089a1d03eSRichard     Sum += Pv->at(I) + 2;
65189a1d03eSRichard   }
65289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
65389a1d03eSRichard   // CHECK-FIXES: for (int I : *Pv)
65489a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
65589a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
65689a1d03eSRichard 
65789a1d03eSRichard   // This test will fail if size() isn't called repeatedly, since it
65889a1d03eSRichard   // returns unsigned int, and 0 is deduced to be signed int.
65989a1d03eSRichard   // FIXME: Insert the necessary explicit conversion, or write out the types
66089a1d03eSRichard   // explicitly.
66189a1d03eSRichard   for (int I = 0; I < Pv->size(); ++I) {
66289a1d03eSRichard     printf("Fibonacci number is %d\n", (*Pv).at(I));
66389a1d03eSRichard     Sum += (*Pv)[I] + 2;
66489a1d03eSRichard   }
66589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
66689a1d03eSRichard   // CHECK-FIXES: for (int I : *Pv)
66789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
66889a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
66989a1d03eSRichard 
67089a1d03eSRichard   for (int I = 0; I < Cv->size(); ++I) {
67189a1d03eSRichard     printf("Fibonacci number is %d\n", Cv->at(I));
67289a1d03eSRichard     Sum += Cv->at(I) + 2;
67389a1d03eSRichard   }
67489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
67589a1d03eSRichard   // CHECK-FIXES: for (int I : *Cv)
67689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
67789a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
67889a1d03eSRichard 
67989a1d03eSRichard   for (int I = 0, E = V.size(); E > I; ++I) {
68089a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
68189a1d03eSRichard     Sum += V[I] + 2;
68289a1d03eSRichard   }
68389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
68489a1d03eSRichard   // CHECK-FIXES: for (int I : V)
68589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
68689a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
68789a1d03eSRichard 
68889a1d03eSRichard   for (int I = 0, E = V.size(); I != E; ++I) {
68989a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
69089a1d03eSRichard     Sum += V[I] + 2;
69189a1d03eSRichard   }
69289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
69389a1d03eSRichard   // CHECK-FIXES: for (int I : V)
69489a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
69589a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
69689a1d03eSRichard 
69789a1d03eSRichard   for (int I = 0, E = V.size(); E != I; ++I) {
69889a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
69989a1d03eSRichard     Sum += V[I] + 2;
70089a1d03eSRichard   }
70189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
70289a1d03eSRichard   // CHECK-FIXES: for (int I : V)
70389a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
70489a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
705e4329520SChris Cotter 
706e4329520SChris Cotter   for (int I = 0, E = VD.size(); E != I; ++I) {
707e4329520SChris Cotter     printf("Fibonacci number is %d\n", VD[I]);
708e4329520SChris Cotter     Sum += VD[I] + 2;
709e4329520SChris Cotter   }
710e4329520SChris Cotter   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
711e4329520SChris Cotter   // CHECK-FIXES: for (int I : VD)
712e4329520SChris Cotter   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
713e4329520SChris Cotter   // CHECK-FIXES-NEXT: Sum += I + 2;
7146a1f8ef8SChris Cotter 
7156a1f8ef8SChris Cotter   for (int I = 0, E = size(V); E != I; ++I) {
7166a1f8ef8SChris Cotter     printf("Fibonacci number is %d\n", V[I]);
7176a1f8ef8SChris Cotter     Sum += V[I] + 2;
7186a1f8ef8SChris Cotter   }
7196a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
7206a1f8ef8SChris Cotter   // CHECK-FIXES: for (int I : V)
7216a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
7226a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: Sum += I + 2;
7236a1f8ef8SChris Cotter 
7246a1f8ef8SChris Cotter   for (int I = 0, E = size(V); E != I; ++I) {
7256a1f8ef8SChris Cotter     V[I] = 0;
7266a1f8ef8SChris Cotter   }
7276a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
7286a1f8ef8SChris Cotter   // CHECK-FIXES: for (int & I : V)
7296a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: I = 0;
7306a1f8ef8SChris Cotter 
7316a1f8ef8SChris Cotter   for (int I = 0, E = std::size(V); E != I; ++I) {
7326a1f8ef8SChris Cotter     V[I] = 0;
7336a1f8ef8SChris Cotter   }
7346a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
7356a1f8ef8SChris Cotter   // CHECK-FIXES: for (int & I : V)
7366a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: I = 0;
7376a1f8ef8SChris Cotter 
7386a1f8ef8SChris Cotter   // Although 'length' might be a valid free function, only size() is standardized
7396a1f8ef8SChris Cotter   for (int I = 0, E = length(V); E != I; ++I) {
7406a1f8ef8SChris Cotter     printf("Fibonacci number is %d\n", V[I]);
7416a1f8ef8SChris Cotter     Sum += V[I] + 2;
7426a1f8ef8SChris Cotter   }
7436a1f8ef8SChris Cotter 
7446a1f8ef8SChris Cotter   dependent<Val> Vals;
7456a1f8ef8SChris Cotter   for (int I = 0, E = size(Vals); E != I; ++I) {
7466a1f8ef8SChris Cotter     Sum += Vals[I].X;
7476a1f8ef8SChris Cotter   }
7486a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
7496a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & Val : Vals)
7506a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: Sum += Val.X;
75189a1d03eSRichard }
75289a1d03eSRichard 
75389a1d03eSRichard // Ensure that 'const auto &' is used with containers of non-trivial types.
75489a1d03eSRichard void constness() {
75589a1d03eSRichard   int Sum = 0;
75689a1d03eSRichard   for (int I = 0, E = Constv.size(); I < E; ++I) {
75789a1d03eSRichard     printf("Fibonacci number is %d\n", Constv[I].X);
75889a1d03eSRichard     Sum += Constv[I].X + 2;
75989a1d03eSRichard   }
76089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
76189a1d03eSRichard   // CHECK-FIXES: for (const auto & I : Constv)
76289a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
76389a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
76489a1d03eSRichard 
76589a1d03eSRichard   for (int I = 0, E = Constv.size(); I < E; ++I) {
76689a1d03eSRichard     printf("Fibonacci number is %d\n", Constv.at(I).X);
76789a1d03eSRichard     Sum += Constv.at(I).X + 2;
76889a1d03eSRichard   }
76989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
77089a1d03eSRichard   // CHECK-FIXES: for (const auto & I : Constv)
77189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
77289a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
77389a1d03eSRichard 
77489a1d03eSRichard   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
77589a1d03eSRichard     printf("Fibonacci number is %d\n", Pconstv->at(I).X);
77689a1d03eSRichard     Sum += Pconstv->at(I).X + 2;
77789a1d03eSRichard   }
77889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
77989a1d03eSRichard   // CHECK-FIXES: for (const auto & I : *Pconstv)
78089a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
78189a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
78289a1d03eSRichard 
78389a1d03eSRichard   // This test will fail if size() isn't called repeatedly, since it
78489a1d03eSRichard   // returns unsigned int, and 0 is deduced to be signed int.
78589a1d03eSRichard   // FIXME: Insert the necessary explicit conversion, or write out the types
78689a1d03eSRichard   // explicitly.
78789a1d03eSRichard   for (int I = 0; I < Pconstv->size(); ++I) {
78889a1d03eSRichard     printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
78989a1d03eSRichard     Sum += (*Pconstv)[I].X + 2;
79089a1d03eSRichard   }
79189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
79289a1d03eSRichard   // CHECK-FIXES: for (const auto & I : *Pconstv)
79389a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
79489a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
79589a1d03eSRichard }
79689a1d03eSRichard 
79789a1d03eSRichard void constRef(const dependent<int>& ConstVRef) {
79889a1d03eSRichard   int sum = 0;
79989a1d03eSRichard   // FIXME: This does not work with size_t (probably due to the implementation
80089a1d03eSRichard   // of dependent); make dependent work exactly like a std container type.
80189a1d03eSRichard   for (int I = 0; I < ConstVRef.size(); ++I) {
80289a1d03eSRichard     sum += ConstVRef[I];
80389a1d03eSRichard   }
80489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
80589a1d03eSRichard   // CHECK-FIXES: for (int I : ConstVRef)
80689a1d03eSRichard   // CHECK-FIXES-NEXT: sum += I;
80789a1d03eSRichard 
80889a1d03eSRichard   for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
80989a1d03eSRichard     sum += *I;
81089a1d03eSRichard   }
81189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
81289a1d03eSRichard   // CHECK-FIXES: for (int I : ConstVRef)
81389a1d03eSRichard   // CHECK-FIXES-NEXT: sum += I;
81489a1d03eSRichard }
81589a1d03eSRichard 
81689a1d03eSRichard // Check for loops that don't mention containers.
81789a1d03eSRichard void noContainer() {
81889a1d03eSRichard   for (auto I = 0; I < V.size(); ++I) {
81989a1d03eSRichard   }
82089a1d03eSRichard 
82189a1d03eSRichard   for (auto I = 0; I < V.size(); ++I)
82289a1d03eSRichard     ;
82389a1d03eSRichard }
82489a1d03eSRichard 
82589a1d03eSRichard struct NoBeginEnd {
82689a1d03eSRichard   unsigned size() const;
82789a1d03eSRichard   unsigned& operator[](int);
82889a1d03eSRichard   const unsigned& operator[](int) const;
82989a1d03eSRichard };
83089a1d03eSRichard 
83189a1d03eSRichard struct NoConstBeginEnd {
83289a1d03eSRichard   NoConstBeginEnd();
83389a1d03eSRichard   unsigned size() const;
83489a1d03eSRichard   unsigned* begin();
83589a1d03eSRichard   unsigned* end();
83689a1d03eSRichard   unsigned& operator[](int);
83789a1d03eSRichard   const unsigned& operator[](int) const;
83889a1d03eSRichard };
83989a1d03eSRichard 
84089a1d03eSRichard struct ConstBeginEnd {
84189a1d03eSRichard   ConstBeginEnd();
84289a1d03eSRichard   unsigned size() const;
84389a1d03eSRichard   unsigned* begin() const;
84489a1d03eSRichard   unsigned* end() const;
84589a1d03eSRichard   unsigned& operator[](int);
84689a1d03eSRichard   const unsigned& operator[](int) const;
84789a1d03eSRichard };
84889a1d03eSRichard 
84989a1d03eSRichard // Shouldn't transform pseudo-array uses if the container doesn't provide
85089a1d03eSRichard // begin() and end() of the right const-ness.
85189a1d03eSRichard void NoBeginEndTest() {
85289a1d03eSRichard   NoBeginEnd NBE;
85389a1d03eSRichard   for (unsigned I = 0, E = NBE.size(); I < E; ++I)
85489a1d03eSRichard     printf("%d\n", NBE[I]);
85589a1d03eSRichard 
85689a1d03eSRichard   const NoConstBeginEnd Const_NCBE;
85789a1d03eSRichard   for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
85889a1d03eSRichard     printf("%d\n", Const_NCBE[I]);
85989a1d03eSRichard 
86089a1d03eSRichard   ConstBeginEnd CBE;
86189a1d03eSRichard   for (unsigned I = 0, E = CBE.size(); I < E; ++I)
86289a1d03eSRichard     printf("%d\n", CBE[I]);
86389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
86489a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : CBE)
86589a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
86689a1d03eSRichard 
86789a1d03eSRichard   const ConstBeginEnd Const_CBE;
86889a1d03eSRichard   for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
86989a1d03eSRichard     printf("%d\n", Const_CBE[I]);
87089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
87189a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : Const_CBE)
87289a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
87389a1d03eSRichard }
87489a1d03eSRichard 
87589a1d03eSRichard struct DerefByValue {
87689a1d03eSRichard   DerefByValue();
87789a1d03eSRichard   struct iter { unsigned operator*(); };
87889a1d03eSRichard   unsigned size() const;
87989a1d03eSRichard   iter begin();
88089a1d03eSRichard   iter end();
88189a1d03eSRichard   unsigned operator[](int);
88289a1d03eSRichard };
88389a1d03eSRichard 
88489a1d03eSRichard void derefByValueTest() {
88589a1d03eSRichard   DerefByValue DBV;
88689a1d03eSRichard   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
88789a1d03eSRichard     printf("%d\n", DBV[I]);
88889a1d03eSRichard   }
88989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
89089a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : DBV)
89189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
89289a1d03eSRichard 
89389a1d03eSRichard   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
89489a1d03eSRichard     auto f = [DBV, I]() {};
89589a1d03eSRichard     printf("%d\n", DBV[I]);
89689a1d03eSRichard   }
89789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
89889a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : DBV)
89989a1d03eSRichard   // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
90089a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
90189a1d03eSRichard }
90289a1d03eSRichard 
90389a1d03eSRichard void fundamentalTypesTest() {
90489a1d03eSRichard   const int N = 10;
90589a1d03eSRichard   bool Bools[N];
90689a1d03eSRichard   for (int i = 0; i < N; ++i)
90789a1d03eSRichard     printf("%d", Bools[i]);
90889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
90989a1d03eSRichard   // CHECK-FIXES: for (bool Bool : Bools)
91089a1d03eSRichard 
91189a1d03eSRichard   int Ints[N];
91289a1d03eSRichard   unsigned short int Shorts[N];
91389a1d03eSRichard   for (int i = 0; i < N; ++i)
91489a1d03eSRichard     printf("%d", Shorts[i]);
91589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
91689a1d03eSRichard   // CHECK-FIXES: for (unsigned short Short : Shorts)
91789a1d03eSRichard 
91889a1d03eSRichard   signed long Longs[N];
91989a1d03eSRichard   for (int i = 0; i < N; ++i)
92089a1d03eSRichard     printf("%d", Longs[i]);
92189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
92289a1d03eSRichard   // CHECK-FIXES: for (long Long : Longs)
92389a1d03eSRichard 
92489a1d03eSRichard   long long int LongLongs[N];
92589a1d03eSRichard   for (int i = 0; i < N; ++i)
92689a1d03eSRichard     printf("%d", LongLongs[i]);
92789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
92889a1d03eSRichard   // CHECK-FIXES: for (long long LongLong : LongLongs)
92989a1d03eSRichard 
93089a1d03eSRichard   char Chars[N];
93189a1d03eSRichard   for (int i = 0; i < N; ++i)
93289a1d03eSRichard     printf("%d", Chars[i]);
93389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
93489a1d03eSRichard   // CHECK-FIXES: for (char Char : Chars)
93589a1d03eSRichard 
93689a1d03eSRichard   wchar_t WChars[N];
93789a1d03eSRichard   for (int i = 0; i < N; ++i)
93889a1d03eSRichard     printf("%d", WChars[i]);
93989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
94089a1d03eSRichard   // CHECK-FIXES: for (wchar_t WChar : WChars)
94189a1d03eSRichard 
94289a1d03eSRichard   float Floats[N];
94389a1d03eSRichard   for (int i = 0; i < N; ++i)
94489a1d03eSRichard     printf("%d", Floats[i]);
94589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
94689a1d03eSRichard   // CHECK-FIXES: for (float Float : Floats)
94789a1d03eSRichard 
94889a1d03eSRichard   double Doubles[N];
94989a1d03eSRichard   for (int i = 0; i < N; ++i)
95089a1d03eSRichard     printf("%d", Doubles[i]);
95189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
95289a1d03eSRichard   // CHECK-FIXES: for (double Double : Doubles)
95389a1d03eSRichard }
95489a1d03eSRichard 
9555ae5af1dSCongcong Cai template <unsigned  p> void _dependenceArrayTest() {
9565ae5af1dSCongcong Cai   unsigned test[3][p];
9575ae5af1dSCongcong Cai   for (unsigned i = 0; i < p; ++i)
9585ae5af1dSCongcong Cai     for (unsigned j = 0; j < 3; ++j)
9595ae5af1dSCongcong Cai       printf("%d", test[j][i]);
9605ae5af1dSCongcong Cai   // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
9615ae5af1dSCongcong Cai   // CHECK-FIXES: (auto & j : test)
9625ae5af1dSCongcong Cai   // CHECK-FIXES: printf("%d", j[i]);
9635ae5af1dSCongcong Cai }
9645ae5af1dSCongcong Cai void dependenceArrayTest() {
9655ae5af1dSCongcong Cai   _dependenceArrayTest<1>();
9665ae5af1dSCongcong Cai   _dependenceArrayTest<2>();
9675ae5af1dSCongcong Cai }
9685ae5af1dSCongcong Cai 
96989a1d03eSRichard } // namespace PseudoArray
970296fbee5SPiotr Zegar 
971296fbee5SPiotr Zegar namespace PR78381 {
972296fbee5SPiotr Zegar   struct blocked_range {
973296fbee5SPiotr Zegar     int begin() const;
974296fbee5SPiotr Zegar     int end() const;
975296fbee5SPiotr Zegar   };
976296fbee5SPiotr Zegar 
977296fbee5SPiotr Zegar   void test() {
978296fbee5SPiotr Zegar     blocked_range r;
979296fbee5SPiotr Zegar     for (auto i = r.begin(); i!=r.end(); ++i) {
980296fbee5SPiotr Zegar     }
981296fbee5SPiotr Zegar   }
982296fbee5SPiotr Zegar }
983*e984d11dSCongcong Cai 
984*e984d11dSCongcong Cai namespace GH109083 {
985*e984d11dSCongcong Cai void test() {
986*e984d11dSCongcong Cai   const int N = 6;
987*e984d11dSCongcong Cai   int Arr[N] = {1, 2, 3, 4, 5, 6};
988*e984d11dSCongcong Cai 
989*e984d11dSCongcong Cai   for (int I = 0; I < N; ++I) {
990*e984d11dSCongcong Cai     auto V = [T = Arr[I]]() {};
991*e984d11dSCongcong Cai   }
992*e984d11dSCongcong Cai   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
993*e984d11dSCongcong Cai   // CHECK-FIXES: for (int I : Arr)
994*e984d11dSCongcong Cai   // CHECK-FIXES-NEXT: auto V = [T = I]() {};
995*e984d11dSCongcong Cai   for (int I = 0; I < N; ++I) {
996*e984d11dSCongcong Cai     auto V = [T = 10 + Arr[I]]() {};
997*e984d11dSCongcong Cai   }
998*e984d11dSCongcong Cai   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
999*e984d11dSCongcong Cai   // CHECK-FIXES: for (int I : Arr)
1000*e984d11dSCongcong Cai   // CHECK-FIXES-NEXT: auto V = [T = 10 + I]() {};
1001*e984d11dSCongcong Cai 
1002*e984d11dSCongcong Cai   for (int I = 0; I < N; ++I) {
1003*e984d11dSCongcong Cai     auto V = [T = I]() {};
1004*e984d11dSCongcong Cai   }
1005*e984d11dSCongcong Cai   for (int I = 0; I < N; ++I) {
1006*e984d11dSCongcong Cai     auto V = [T = I + 10]() {};
1007*e984d11dSCongcong Cai   }
1008*e984d11dSCongcong Cai }
1009*e984d11dSCongcong Cai } // namespace GH109083
1010