xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp (revision 6a1f8ef8a7aaefea80ef0bc7c6c462a96215b50e)
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);
448*6a1f8ef8SChris Cotter 
449*6a1f8ef8SChris Cotter   for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
450*6a1f8ef8SChris Cotter     printf("s0 has value %d\n", (*It).X);
451*6a1f8ef8SChris Cotter   }
452*6a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
453*6a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & It : Ss)
454*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
455*6a1f8ef8SChris Cotter 
456*6a1f8ef8SChris Cotter   for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
457*6a1f8ef8SChris Cotter     printf("s1 has value %d\n", (*It).X);
458*6a1f8ef8SChris Cotter   }
459*6a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
460*6a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & It : Ss)
461*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
462*6a1f8ef8SChris Cotter 
463*6a1f8ef8SChris Cotter   for (S::iterator It = begin(*Ps), E = end(*Ps); It != E; ++It) {
464*6a1f8ef8SChris Cotter     printf("s2 has value %d\n", (*It).X);
465*6a1f8ef8SChris Cotter   }
466*6a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
467*6a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & It : *Ps)
468*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s2 has value %d\n", It.X);
469*6a1f8ef8SChris Cotter 
470*6a1f8ef8SChris Cotter   for (S::iterator It = begin(*Ps); It != end(*Ps); ++It) {
471*6a1f8ef8SChris Cotter     printf("s3 has value %d\n", (*It).X);
472*6a1f8ef8SChris Cotter   }
473*6a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
474*6a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & It : *Ps)
475*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s3 has value %d\n", It.X);
476*6a1f8ef8SChris Cotter 
477*6a1f8ef8SChris Cotter   for (S::const_iterator It = cbegin(Ss), E = cend(Ss); It != E; ++It) {
478*6a1f8ef8SChris Cotter     printf("s4 has value %d\n", (*It).X);
479*6a1f8ef8SChris Cotter   }
480*6a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
481*6a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto It : Ss)
482*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("s4 has value %d\n", It.X);
48389a1d03eSRichard }
48489a1d03eSRichard 
48589a1d03eSRichard // Tests to verify the proper use of auto where the init variable type and the
48689a1d03eSRichard // initializer type differ or are mostly the same except for const qualifiers.
48789a1d03eSRichard void different_type() {
48889a1d03eSRichard   // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
48989a1d03eSRichard   // differs from const_iterator only on the const qualification.
49089a1d03eSRichard   S Ss;
49189a1d03eSRichard   for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
49289a1d03eSRichard     printf("s has value %d\n", (*It).X);
49389a1d03eSRichard   }
49489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
49589a1d03eSRichard   // CHECK-FIXES: for (auto It : Ss)
49689a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
49789a1d03eSRichard 
49889a1d03eSRichard   S *Ps;
49989a1d03eSRichard   for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
50089a1d03eSRichard     printf("s has value %d\n", (*It).X);
50189a1d03eSRichard   }
50289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
50389a1d03eSRichard   // CHECK-FIXES: for (auto P : *Ps)
50489a1d03eSRichard   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
50589a1d03eSRichard 
50689a1d03eSRichard   dependent<int> V;
50789a1d03eSRichard   for (dependent<int>::const_iterator It = V.begin(), E = V.end();
50889a1d03eSRichard        It != E; ++It) {
50989a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
51089a1d03eSRichard   }
51189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
51289a1d03eSRichard   // CHECK-FIXES: for (int It : V)
51389a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
51489a1d03eSRichard 
51589a1d03eSRichard   for (dependent<int>::const_iterator It(V.begin()), E = V.end();
51689a1d03eSRichard        It != E; ++It) {
51789a1d03eSRichard     printf("Fibonacci number is %d\n", *It);
51889a1d03eSRichard   }
51989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
52089a1d03eSRichard   // CHECK-FIXES: for (int It : V)
52189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
52289a1d03eSRichard }
52389a1d03eSRichard 
52489a1d03eSRichard // Tests to ensure that an implicit 'this' is picked up as the container.
52589a1d03eSRichard // If member calls are made to 'this' within the loop, the transform becomes
52689a1d03eSRichard // risky as these calls may affect state that affects the loop.
52789a1d03eSRichard class C {
52889a1d03eSRichard public:
52989a1d03eSRichard   typedef MutableVal *iterator;
53089a1d03eSRichard   typedef const MutableVal *const_iterator;
53189a1d03eSRichard 
53289a1d03eSRichard   iterator begin();
53389a1d03eSRichard   iterator end();
53489a1d03eSRichard   const_iterator begin() const;
53589a1d03eSRichard   const_iterator end() const;
53689a1d03eSRichard 
53789a1d03eSRichard   void doSomething();
53889a1d03eSRichard   void doSomething() const;
53989a1d03eSRichard 
54089a1d03eSRichard   void doLoop() {
54189a1d03eSRichard     for (iterator I = begin(), E = end(); I != E; ++I)
54289a1d03eSRichard       (void) *I;
54389a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
54489a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
54589a1d03eSRichard 
54689a1d03eSRichard     for (iterator I = C::begin(), E = C::end(); I != E; ++I)
54789a1d03eSRichard       (void) *I;
54889a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
54989a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
55089a1d03eSRichard 
55189a1d03eSRichard     for (iterator I = begin(), E = end(); I != E; ++I) {
55289a1d03eSRichard       (void) *I;
55389a1d03eSRichard       doSomething();
55489a1d03eSRichard     }
55589a1d03eSRichard 
55689a1d03eSRichard     for (iterator I = begin(); I != end(); ++I)
55789a1d03eSRichard       (void) *I;
55889a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
55989a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
56089a1d03eSRichard 
56189a1d03eSRichard     for (iterator I = begin(); I != end(); ++I) {
56289a1d03eSRichard       (void) *I;
56389a1d03eSRichard       doSomething();
56489a1d03eSRichard     }
56589a1d03eSRichard   }
56689a1d03eSRichard 
56789a1d03eSRichard   void doLoop() const {
56889a1d03eSRichard     for (const_iterator I = begin(), E = end(); I != E; ++I)
56989a1d03eSRichard       (void) *I;
57089a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
57189a1d03eSRichard     // CHECK-FIXES: for (auto I : *this)
57289a1d03eSRichard 
57389a1d03eSRichard     for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
57489a1d03eSRichard       (void) *I;
57589a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
57689a1d03eSRichard     // CHECK-FIXES: for (auto I : *this)
57789a1d03eSRichard 
57889a1d03eSRichard     for (const_iterator I = begin(), E = end(); I != E; ++I) {
57989a1d03eSRichard       (void) *I;
58089a1d03eSRichard       doSomething();
58189a1d03eSRichard     }
58289a1d03eSRichard   }
58389a1d03eSRichard };
58489a1d03eSRichard 
58589a1d03eSRichard class C2 {
58689a1d03eSRichard public:
58789a1d03eSRichard   typedef MutableVal *iterator;
58889a1d03eSRichard 
58989a1d03eSRichard   iterator begin() const;
59089a1d03eSRichard   iterator end() const;
59189a1d03eSRichard 
59289a1d03eSRichard   void doLoop() {
59389a1d03eSRichard     // The implicit 'this' will have an Implicit cast to const C2* wrapped
59489a1d03eSRichard     // around it. Make sure the replacement still happens.
59589a1d03eSRichard     for (iterator I = begin(), E = end(); I != E; ++I)
59689a1d03eSRichard       (void) *I;
59789a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
59889a1d03eSRichard     // CHECK-FIXES: for (auto & I : *this)
59989a1d03eSRichard   }
60089a1d03eSRichard };
60189a1d03eSRichard 
60289a1d03eSRichard } // namespace Iterator
60389a1d03eSRichard 
60489a1d03eSRichard namespace PseudoArray {
60589a1d03eSRichard 
60689a1d03eSRichard const int N = 6;
60789a1d03eSRichard dependent<int> V;
60889a1d03eSRichard dependent<int> *Pv;
60989a1d03eSRichard const dependent<NonTriviallyCopyable> Constv;
61089a1d03eSRichard const dependent<NonTriviallyCopyable> *Pconstv;
61189a1d03eSRichard 
61289a1d03eSRichard transparent<dependent<int>> Cv;
613e4329520SChris Cotter dependent_derived<int> VD;
61489a1d03eSRichard 
61589a1d03eSRichard void f() {
61689a1d03eSRichard   int Sum = 0;
61789a1d03eSRichard   for (int I = 0, E = V.size(); I < E; ++I) {
61889a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
61989a1d03eSRichard     Sum += V[I] + 2;
62089a1d03eSRichard   }
62189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
62289a1d03eSRichard   // CHECK-FIXES: for (int I : V)
62389a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
62489a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
62589a1d03eSRichard 
62689a1d03eSRichard   for (int I = 0, E = V.size(); I < E; ++I) {
62789a1d03eSRichard     printf("Fibonacci number is %d\n", V.at(I));
62889a1d03eSRichard     Sum += V.at(I) + 2;
62989a1d03eSRichard   }
63089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
63189a1d03eSRichard   // CHECK-FIXES: for (int I : V)
63289a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
63389a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
63489a1d03eSRichard 
63589a1d03eSRichard   for (int I = 0, E = Pv->size(); I < E; ++I) {
63689a1d03eSRichard     printf("Fibonacci number is %d\n", Pv->at(I));
63789a1d03eSRichard     Sum += Pv->at(I) + 2;
63889a1d03eSRichard   }
63989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
64089a1d03eSRichard   // CHECK-FIXES: for (int I : *Pv)
64189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
64289a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
64389a1d03eSRichard 
64489a1d03eSRichard   // This test will fail if size() isn't called repeatedly, since it
64589a1d03eSRichard   // returns unsigned int, and 0 is deduced to be signed int.
64689a1d03eSRichard   // FIXME: Insert the necessary explicit conversion, or write out the types
64789a1d03eSRichard   // explicitly.
64889a1d03eSRichard   for (int I = 0; I < Pv->size(); ++I) {
64989a1d03eSRichard     printf("Fibonacci number is %d\n", (*Pv).at(I));
65089a1d03eSRichard     Sum += (*Pv)[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   for (int I = 0; I < Cv->size(); ++I) {
65889a1d03eSRichard     printf("Fibonacci number is %d\n", Cv->at(I));
65989a1d03eSRichard     Sum += Cv->at(I) + 2;
66089a1d03eSRichard   }
66189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
66289a1d03eSRichard   // CHECK-FIXES: for (int I : *Cv)
66389a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
66489a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
66589a1d03eSRichard 
66689a1d03eSRichard   for (int I = 0, E = V.size(); E > I; ++I) {
66789a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
66889a1d03eSRichard     Sum += V[I] + 2;
66989a1d03eSRichard   }
67089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
67189a1d03eSRichard   // CHECK-FIXES: for (int I : V)
67289a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
67389a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
67489a1d03eSRichard 
67589a1d03eSRichard   for (int I = 0, E = V.size(); I != E; ++I) {
67689a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
67789a1d03eSRichard     Sum += V[I] + 2;
67889a1d03eSRichard   }
67989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
68089a1d03eSRichard   // CHECK-FIXES: for (int I : V)
68189a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
68289a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
68389a1d03eSRichard 
68489a1d03eSRichard   for (int I = 0, E = V.size(); E != I; ++I) {
68589a1d03eSRichard     printf("Fibonacci number is %d\n", V[I]);
68689a1d03eSRichard     Sum += V[I] + 2;
68789a1d03eSRichard   }
68889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
68989a1d03eSRichard   // CHECK-FIXES: for (int I : V)
69089a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
69189a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I + 2;
692e4329520SChris Cotter 
693e4329520SChris Cotter   for (int I = 0, E = VD.size(); E != I; ++I) {
694e4329520SChris Cotter     printf("Fibonacci number is %d\n", VD[I]);
695e4329520SChris Cotter     Sum += VD[I] + 2;
696e4329520SChris Cotter   }
697e4329520SChris Cotter   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
698e4329520SChris Cotter   // CHECK-FIXES: for (int I : VD)
699e4329520SChris Cotter   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
700e4329520SChris Cotter   // CHECK-FIXES-NEXT: Sum += I + 2;
701*6a1f8ef8SChris Cotter 
702*6a1f8ef8SChris Cotter   for (int I = 0, E = size(V); E != I; ++I) {
703*6a1f8ef8SChris Cotter     printf("Fibonacci number is %d\n", V[I]);
704*6a1f8ef8SChris Cotter     Sum += V[I] + 2;
705*6a1f8ef8SChris Cotter   }
706*6a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
707*6a1f8ef8SChris Cotter   // CHECK-FIXES: for (int I : V)
708*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
709*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: Sum += I + 2;
710*6a1f8ef8SChris Cotter 
711*6a1f8ef8SChris Cotter   for (int I = 0, E = size(V); E != I; ++I) {
712*6a1f8ef8SChris Cotter     V[I] = 0;
713*6a1f8ef8SChris Cotter   }
714*6a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
715*6a1f8ef8SChris Cotter   // CHECK-FIXES: for (int & I : V)
716*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: I = 0;
717*6a1f8ef8SChris Cotter 
718*6a1f8ef8SChris Cotter   for (int I = 0, E = std::size(V); E != I; ++I) {
719*6a1f8ef8SChris Cotter     V[I] = 0;
720*6a1f8ef8SChris Cotter   }
721*6a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
722*6a1f8ef8SChris Cotter   // CHECK-FIXES: for (int & I : V)
723*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: I = 0;
724*6a1f8ef8SChris Cotter 
725*6a1f8ef8SChris Cotter   // Although 'length' might be a valid free function, only size() is standardized
726*6a1f8ef8SChris Cotter   for (int I = 0, E = length(V); E != I; ++I) {
727*6a1f8ef8SChris Cotter     printf("Fibonacci number is %d\n", V[I]);
728*6a1f8ef8SChris Cotter     Sum += V[I] + 2;
729*6a1f8ef8SChris Cotter   }
730*6a1f8ef8SChris Cotter 
731*6a1f8ef8SChris Cotter   dependent<Val> Vals;
732*6a1f8ef8SChris Cotter   for (int I = 0, E = size(Vals); E != I; ++I) {
733*6a1f8ef8SChris Cotter     Sum += Vals[I].X;
734*6a1f8ef8SChris Cotter   }
735*6a1f8ef8SChris Cotter   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
736*6a1f8ef8SChris Cotter   // CHECK-FIXES: for (auto & Val : Vals)
737*6a1f8ef8SChris Cotter   // CHECK-FIXES-NEXT: Sum += Val.X;
73889a1d03eSRichard }
73989a1d03eSRichard 
74089a1d03eSRichard // Ensure that 'const auto &' is used with containers of non-trivial types.
74189a1d03eSRichard void constness() {
74289a1d03eSRichard   int Sum = 0;
74389a1d03eSRichard   for (int I = 0, E = Constv.size(); I < E; ++I) {
74489a1d03eSRichard     printf("Fibonacci number is %d\n", Constv[I].X);
74589a1d03eSRichard     Sum += Constv[I].X + 2;
74689a1d03eSRichard   }
74789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
74889a1d03eSRichard   // CHECK-FIXES: for (const auto & I : Constv)
74989a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
75089a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
75189a1d03eSRichard 
75289a1d03eSRichard   for (int I = 0, E = Constv.size(); I < E; ++I) {
75389a1d03eSRichard     printf("Fibonacci number is %d\n", Constv.at(I).X);
75489a1d03eSRichard     Sum += Constv.at(I).X + 2;
75589a1d03eSRichard   }
75689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
75789a1d03eSRichard   // CHECK-FIXES: for (const auto & I : Constv)
75889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
75989a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
76089a1d03eSRichard 
76189a1d03eSRichard   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
76289a1d03eSRichard     printf("Fibonacci number is %d\n", Pconstv->at(I).X);
76389a1d03eSRichard     Sum += Pconstv->at(I).X + 2;
76489a1d03eSRichard   }
76589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
76689a1d03eSRichard   // CHECK-FIXES: for (const auto & I : *Pconstv)
76789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
76889a1d03eSRichard   // CHECK-FIXES-NEXT: Sum += I.X + 2;
76989a1d03eSRichard 
77089a1d03eSRichard   // This test will fail if size() isn't called repeatedly, since it
77189a1d03eSRichard   // returns unsigned int, and 0 is deduced to be signed int.
77289a1d03eSRichard   // FIXME: Insert the necessary explicit conversion, or write out the types
77389a1d03eSRichard   // explicitly.
77489a1d03eSRichard   for (int I = 0; I < Pconstv->size(); ++I) {
77589a1d03eSRichard     printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
77689a1d03eSRichard     Sum += (*Pconstv)[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 
78489a1d03eSRichard void constRef(const dependent<int>& ConstVRef) {
78589a1d03eSRichard   int sum = 0;
78689a1d03eSRichard   // FIXME: This does not work with size_t (probably due to the implementation
78789a1d03eSRichard   // of dependent); make dependent work exactly like a std container type.
78889a1d03eSRichard   for (int I = 0; I < ConstVRef.size(); ++I) {
78989a1d03eSRichard     sum += ConstVRef[I];
79089a1d03eSRichard   }
79189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
79289a1d03eSRichard   // CHECK-FIXES: for (int I : ConstVRef)
79389a1d03eSRichard   // CHECK-FIXES-NEXT: sum += I;
79489a1d03eSRichard 
79589a1d03eSRichard   for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
79689a1d03eSRichard     sum += *I;
79789a1d03eSRichard   }
79889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
79989a1d03eSRichard   // CHECK-FIXES: for (int I : ConstVRef)
80089a1d03eSRichard   // CHECK-FIXES-NEXT: sum += I;
80189a1d03eSRichard }
80289a1d03eSRichard 
80389a1d03eSRichard // Check for loops that don't mention containers.
80489a1d03eSRichard void noContainer() {
80589a1d03eSRichard   for (auto I = 0; I < V.size(); ++I) {
80689a1d03eSRichard   }
80789a1d03eSRichard 
80889a1d03eSRichard   for (auto I = 0; I < V.size(); ++I)
80989a1d03eSRichard     ;
81089a1d03eSRichard }
81189a1d03eSRichard 
81289a1d03eSRichard struct NoBeginEnd {
81389a1d03eSRichard   unsigned size() const;
81489a1d03eSRichard   unsigned& operator[](int);
81589a1d03eSRichard   const unsigned& operator[](int) const;
81689a1d03eSRichard };
81789a1d03eSRichard 
81889a1d03eSRichard struct NoConstBeginEnd {
81989a1d03eSRichard   NoConstBeginEnd();
82089a1d03eSRichard   unsigned size() const;
82189a1d03eSRichard   unsigned* begin();
82289a1d03eSRichard   unsigned* end();
82389a1d03eSRichard   unsigned& operator[](int);
82489a1d03eSRichard   const unsigned& operator[](int) const;
82589a1d03eSRichard };
82689a1d03eSRichard 
82789a1d03eSRichard struct ConstBeginEnd {
82889a1d03eSRichard   ConstBeginEnd();
82989a1d03eSRichard   unsigned size() const;
83089a1d03eSRichard   unsigned* begin() const;
83189a1d03eSRichard   unsigned* end() const;
83289a1d03eSRichard   unsigned& operator[](int);
83389a1d03eSRichard   const unsigned& operator[](int) const;
83489a1d03eSRichard };
83589a1d03eSRichard 
83689a1d03eSRichard // Shouldn't transform pseudo-array uses if the container doesn't provide
83789a1d03eSRichard // begin() and end() of the right const-ness.
83889a1d03eSRichard void NoBeginEndTest() {
83989a1d03eSRichard   NoBeginEnd NBE;
84089a1d03eSRichard   for (unsigned I = 0, E = NBE.size(); I < E; ++I)
84189a1d03eSRichard     printf("%d\n", NBE[I]);
84289a1d03eSRichard 
84389a1d03eSRichard   const NoConstBeginEnd Const_NCBE;
84489a1d03eSRichard   for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
84589a1d03eSRichard     printf("%d\n", Const_NCBE[I]);
84689a1d03eSRichard 
84789a1d03eSRichard   ConstBeginEnd CBE;
84889a1d03eSRichard   for (unsigned I = 0, E = CBE.size(); I < E; ++I)
84989a1d03eSRichard     printf("%d\n", CBE[I]);
85089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
85189a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : CBE)
85289a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
85389a1d03eSRichard 
85489a1d03eSRichard   const ConstBeginEnd Const_CBE;
85589a1d03eSRichard   for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
85689a1d03eSRichard     printf("%d\n", Const_CBE[I]);
85789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
85889a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : Const_CBE)
85989a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
86089a1d03eSRichard }
86189a1d03eSRichard 
86289a1d03eSRichard struct DerefByValue {
86389a1d03eSRichard   DerefByValue();
86489a1d03eSRichard   struct iter { unsigned operator*(); };
86589a1d03eSRichard   unsigned size() const;
86689a1d03eSRichard   iter begin();
86789a1d03eSRichard   iter end();
86889a1d03eSRichard   unsigned operator[](int);
86989a1d03eSRichard };
87089a1d03eSRichard 
87189a1d03eSRichard void derefByValueTest() {
87289a1d03eSRichard   DerefByValue DBV;
87389a1d03eSRichard   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
87489a1d03eSRichard     printf("%d\n", DBV[I]);
87589a1d03eSRichard   }
87689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
87789a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : DBV)
87889a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
87989a1d03eSRichard 
88089a1d03eSRichard   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
88189a1d03eSRichard     auto f = [DBV, I]() {};
88289a1d03eSRichard     printf("%d\n", DBV[I]);
88389a1d03eSRichard   }
88489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
88589a1d03eSRichard   // CHECK-FIXES: for (unsigned int I : DBV)
88689a1d03eSRichard   // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
88789a1d03eSRichard   // CHECK-FIXES-NEXT: printf("%d\n", I);
88889a1d03eSRichard }
88989a1d03eSRichard 
89089a1d03eSRichard void fundamentalTypesTest() {
89189a1d03eSRichard   const int N = 10;
89289a1d03eSRichard   bool Bools[N];
89389a1d03eSRichard   for (int i = 0; i < N; ++i)
89489a1d03eSRichard     printf("%d", Bools[i]);
89589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
89689a1d03eSRichard   // CHECK-FIXES: for (bool Bool : Bools)
89789a1d03eSRichard 
89889a1d03eSRichard   int Ints[N];
89989a1d03eSRichard   unsigned short int Shorts[N];
90089a1d03eSRichard   for (int i = 0; i < N; ++i)
90189a1d03eSRichard     printf("%d", Shorts[i]);
90289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
90389a1d03eSRichard   // CHECK-FIXES: for (unsigned short Short : Shorts)
90489a1d03eSRichard 
90589a1d03eSRichard   signed long Longs[N];
90689a1d03eSRichard   for (int i = 0; i < N; ++i)
90789a1d03eSRichard     printf("%d", Longs[i]);
90889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
90989a1d03eSRichard   // CHECK-FIXES: for (long Long : Longs)
91089a1d03eSRichard 
91189a1d03eSRichard   long long int LongLongs[N];
91289a1d03eSRichard   for (int i = 0; i < N; ++i)
91389a1d03eSRichard     printf("%d", LongLongs[i]);
91489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
91589a1d03eSRichard   // CHECK-FIXES: for (long long LongLong : LongLongs)
91689a1d03eSRichard 
91789a1d03eSRichard   char Chars[N];
91889a1d03eSRichard   for (int i = 0; i < N; ++i)
91989a1d03eSRichard     printf("%d", Chars[i]);
92089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
92189a1d03eSRichard   // CHECK-FIXES: for (char Char : Chars)
92289a1d03eSRichard 
92389a1d03eSRichard   wchar_t WChars[N];
92489a1d03eSRichard   for (int i = 0; i < N; ++i)
92589a1d03eSRichard     printf("%d", WChars[i]);
92689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
92789a1d03eSRichard   // CHECK-FIXES: for (wchar_t WChar : WChars)
92889a1d03eSRichard 
92989a1d03eSRichard   float Floats[N];
93089a1d03eSRichard   for (int i = 0; i < N; ++i)
93189a1d03eSRichard     printf("%d", Floats[i]);
93289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
93389a1d03eSRichard   // CHECK-FIXES: for (float Float : Floats)
93489a1d03eSRichard 
93589a1d03eSRichard   double Doubles[N];
93689a1d03eSRichard   for (int i = 0; i < N; ++i)
93789a1d03eSRichard     printf("%d", Doubles[i]);
93889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
93989a1d03eSRichard   // CHECK-FIXES: for (double Double : Doubles)
94089a1d03eSRichard }
94189a1d03eSRichard 
94289a1d03eSRichard } // namespace PseudoArray
943