// Check for loops that don't mention containers void noContainer() { for (auto i = 0; i < v.size(); ++i) { } // CHECK: for (auto & elem : v) { } for (auto i = 0; i < v.size(); ++i) ; // CHECK: for (auto & elem : v) ; }
// Check for loops that don't mention containers. void noContainer() { for (auto i = 0; i < v.size(); ++i) { } for (auto i = 0; i < v.size(); ++i) ; }
// Check for loops that don't mention containers. void noContainer() { for (auto I = 0; I < V.size(); ++I) { } for (auto I = 0; I < V.size(); ++I) ; }
// Checks to see that non-const member functions are not called on the container // object. // These could be conceivably allowed with a lower required confidence level. void memberFunctionCalled() { for (int i = 0; i < v.size(); ++i) { sum += v[i]; v.foo(); } for (int i = 0; i < v.size(); ++i) { sum += v[i]; dependent<int>::iterator it = v.begin(); } }
// Check for loops that don't mention containers. void noContainer() { for (auto i = 0; i < v.size(); ++i) { } // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & elem : v) { for (auto i = 0; i < v.size(); ++i) ; // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & elem : v) }
// Checks for invalid increment steps: void increment() { for (int i = 0; i < v.size(); --i) sum += v[i]; for (int i = 0; i < v.size(); i) sum += v[i]; for (int i = 0; i < v.size();) sum += v[i]; for (int i = 0; i < v.size(); i += 2) sum ++; }
void f() { int Sum = 0; for (int I = 0, E = V.size(); I < E; ++I) { printf("Fibonacci number is %d\n", V[I]); Sum += V[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Elem : V) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; for (int I = 0, E = V.size(); I < E; ++I) { printf("Fibonacci number is %d\n", V.at(I)); Sum += V.at(I) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Elem : V) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; for (int I = 0, E = Pv->size(); I < E; ++I) { printf("Fibonacci number is %d\n", Pv->at(I)); Sum += Pv->at(I) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Elem : *Pv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; // This test will fail if size() isn't called repeatedly, since it // returns unsigned int, and 0 is deduced to be signed int. // FIXME: Insert the necessary explicit conversion, or write out the types // explicitly. for (int I = 0; I < Pv->size(); ++I) { printf("Fibonacci number is %d\n", (*Pv).at(I)); Sum += (*Pv)[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Elem : *Pv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; for (int I = 0; I < Cv->size(); ++I) { printf("Fibonacci number is %d\n", Cv->at(I)); Sum += Cv->at(I) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Elem : *Cv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; }
void f() { int sum = 0; for (int i = 0, e = v.size(); i < e; ++i) { printf("Fibonacci number is %d\n", v[i]); sum += v[i] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : v) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", elem); // CHECK-FIXES-NEXT: sum += elem + 2; for (int i = 0, e = v.size(); i < e; ++i) { printf("Fibonacci number is %d\n", v.at(i)); sum += v.at(i) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : v) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", elem); // CHECK-FIXES-NEXT: sum += elem + 2; for (int i = 0, e = pv->size(); i < e; ++i) { printf("Fibonacci number is %d\n", pv->at(i)); sum += pv->at(i) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : *pv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", elem); // CHECK-FIXES-NEXT: sum += elem + 2; // This test will fail if size() isn't called repeatedly, since it // returns unsigned int, and 0 is deduced to be signed int. // FIXME: Insert the necessary explicit conversion, or write out the types // explicitly. for (int i = 0; i < pv->size(); ++i) { printf("Fibonacci number is %d\n", (*pv).at(i)); sum += (*pv)[i] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : *pv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", elem); // CHECK-FIXES-NEXT: sum += elem + 2; for (int i = 0; i < cv->size(); ++i) { printf("Fibonacci number is %d\n", cv->at(i)); sum += cv->at(i) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : *cv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", elem); // CHECK-FIXES-NEXT: sum += elem + 2; }
// Checks for incorrect loop variables. void mixedVariables() { int badIndex; for (int i = 0; badIndex < v.size(); ++i) sum += v[i]; for (int i = 0; i < v.size(); ++badIndex) sum += v[i]; for (int i = 0; badIndex < v.size(); ++badIndex) sum += v[i]; for (int i = 0; badIndex < v.size(); ++badIndex) sum += v[badIndex]; }
// Checks for the index start and end: void indexStartAndEnd() { for (int i = 0; i < v.size() + 1; ++i) sum += v[i]; for (int i = 0; i < v.size() - 1; ++i) sum += v[i]; for (int i = 1; i < v.size(); ++i) sum += v[i]; for (int i = 1; i < v.size(); ++i) sum += v[i]; for (int i = 0; ; ++i) sum += (*pv)[i]; }
// Checks for an array indexed in addition to the container. void multipleArrays() { int badArr[N]; for (int i = 0; i < v.size(); ++i) sum += v[i] + badArr[i]; for (int i = 0; i < v.size(); ++i) sum += badArr[i]; for (int i = 0; i < v.size(); ++i) { int k = badArr[i]; sum += k + 2; } for (int i = 0; i < v.size(); ++i) { int k = badArr[i]; sum += v[i] + k; } }
// Checks for multiple containers being indexed container. void multipleContainers() { dependent<int> badArr; for (int i = 0; i < v.size(); ++i) sum += v[i] + badArr[i]; for (int i = 0; i < v.size(); ++i) sum += badArr[i]; for (int i = 0; i < v.size(); ++i) { int k = badArr[i]; sum += k + 2; } for (int i = 0; i < v.size(); ++i) { int k = badArr[i]; sum += v[i] + k; } }
// Ensure that 'const auto &' is used with containers of non-trivial types. void constness() { int Sum = 0; for (int I = 0, E = Constv.size(); I < E; ++I) { printf("Fibonacci number is %d\n", Constv[I].X); Sum += Constv[I].X + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & Elem : Constv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X); // CHECK-FIXES-NEXT: Sum += Elem.X + 2; for (int I = 0, E = Constv.size(); I < E; ++I) { printf("Fibonacci number is %d\n", Constv.at(I).X); Sum += Constv.at(I).X + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & Elem : Constv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X); // CHECK-FIXES-NEXT: Sum += Elem.X + 2; for (int I = 0, E = Pconstv->size(); I < E; ++I) { printf("Fibonacci number is %d\n", Pconstv->at(I).X); Sum += Pconstv->at(I).X + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & Elem : *Pconstv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X); // CHECK-FIXES-NEXT: Sum += Elem.X + 2; // This test will fail if size() isn't called repeatedly, since it // returns unsigned int, and 0 is deduced to be signed int. // FIXME: Insert the necessary explicit conversion, or write out the types // explicitly. for (int I = 0; I < Pconstv->size(); ++I) { printf("Fibonacci number is %d\n", (*Pconstv).at(I).X); Sum += (*Pconstv)[I].X + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & Elem : *Pconstv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X); // CHECK-FIXES-NEXT: Sum += Elem.X + 2; }
void constRef(const dependent<int>& ConstVRef) { int sum = 0; // FIXME: This does not work with size_t (probably due to the implementation // of dependent); make dependent work exactly like a std container type. for (int i = 0; i < ConstVRef.size(); ++i) { sum += ConstVRef[i]; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Elem : ConstVRef) // CHECK-FIXES-NEXT: sum += Elem; for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) { sum += *I; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Elem : ConstVRef) // CHECK-FIXES-NEXT: sum += Elem; }
void loops() { for (int I = 0; I < N; ++I) { printf("%d\n", Ints[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (int Int : Ints) // CHECK-FIXES-NEXT: printf("%d\n", Int); for (int I = 0; I < N; ++I) { printf("%d\n", Ints_[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (int Int : Ints_) // CHECK-FIXES-NEXT: printf("%d\n", Int); for (int I = 0; I < DInts.size(); ++I) { printf("%d\n", DInts[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (int DInt : DInts) // CHECK-FIXES-NEXT: printf("%d\n", DInt); }
void aliasing() { // If the loop container is only used for a declaration of a temporary // variable to hold each element, we can name the new variable for the // converted range-based loop as the temporary variable's name. // In the following case, "t" is used as a temporary variable to hold each // element, and thus we consider the name "t" aliased to the loop. // The extra blank braces are left as a placeholder for after the variable // declaration is deleted. for (int i = 0; i < N; ++i) { Val &t = Arr[i]; {} int y = t.x; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & t : Arr) // CHECK-FIXES-NOT: Val &{{[a-z_]+}} = // CHECK-FIXES: {} // CHECK-FIXES-NEXT: int y = t.x; // The container was not only used to initialize a temporary loop variable for // the container's elements, so we do not alias the new loop variable. for (int i = 0; i < N; ++i) { Val &t = Arr[i]; int y = t.x; int z = Arr[i].x + t.x; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : Arr) // CHECK-FIXES-NEXT: Val &t = elem; // CHECK-FIXES-NEXT: int y = t.x; // CHECK-FIXES-NEXT: int z = elem.x + t.x; for (int i = 0; i < N; ++i) { Val t = Arr[i]; int y = t.x; int z = Arr[i].x + t.x; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : Arr) // CHECK-FIXES-NEXT: Val t = elem; // CHECK-FIXES-NEXT: int y = t.x; // CHECK-FIXES-NEXT: int z = elem.x + t.x; // The same for pseudo-arrays like std::vector<T> (or here dependent<Val>) // which provide a subscript operator[]. for (int i = 0; i < v.size(); ++i) { Val &t = v[i]; {} int y = t.x; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & t : v) // CHECK-FIXES: {} // CHECK-FIXES-NEXT: int y = t.x; // The same with a call to at() for (int i = 0; i < pv->size(); ++i) { Val &t = pv->at(i); {} int y = t.x; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & t : *pv) // CHECK-FIXES: {} // CHECK-FIXES-NEXT: int y = t.x; for (int i = 0; i < N; ++i) { Val &t = func(Arr[i]); int y = t.x; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : Arr) // CHECK-FIXES-NEXT: Val &t = func(elem); // CHECK-FIXES-NEXT: int y = t.x; int IntArr[N]; for (unsigned i = 0; i < N; ++i) { if (int alias = IntArr[i]) { sideEffect(alias); } } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto alias : IntArr) // CHECK-FIXES-NEXT: if (alias) for (unsigned i = 0; i < N; ++i) { while (int alias = IntArr[i]) { sideEffect(alias); } } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto alias : IntArr) // CHECK-FIXES-NEXT: while (alias) for (unsigned i = 0; i < N; ++i) { switch (int alias = IntArr[i]) { default: sideEffect(alias); } } // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto alias : IntArr) // CHECK-FIXES-NEXT: switch (alias) for (unsigned i = 0; i < N; ++i) { for (int alias = IntArr[i]; alias < N; ++alias) { sideEffect(alias); } } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto alias : IntArr) // CHECK-FIXES-NEXT: for (; alias < N; ++alias) for (unsigned i = 0; i < N; ++i) { for (unsigned j = 0; int alias = IntArr[i]; ++j) { sideEffect(alias); } } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto alias : IntArr) // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j) struct IntRef { IntRef(const int& i); }; for (int i = 0; i < N; ++i) { IntRef Int(IntArr[i]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : IntArr) // CHECK-FIXES-NEXT: IntRef Int(elem); }
// Checks to make sure that the index isn't used outside of the container: void indexUse() { for (int i = 0; i < v.size(); ++i) v[i] += 1 + i; }
void aliasing() { // If the loop container is only used for a declaration of a temporary // variable to hold each element, we can name the new variable for the // converted range-based loop as the temporary variable's name. // In the following case, "T" is used as a temporary variable to hold each // element, and thus we consider the name "T" aliased to the loop. // The extra blank braces are left as a placeholder for after the variable // declaration is deleted. for (int I = 0; I < N; ++I) { Val &T = Arr[I]; {} int Y = T.X; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & T : Arr) // CHECK-FIXES-NOT: Val &{{[a-z_]+}} = // CHECK-FIXES-NEXT: {} // CHECK-FIXES-NEXT: int Y = T.X; // The container was not only used to initialize a temporary loop variable for // the container's elements, so we do not alias the new loop variable. for (int I = 0; I < N; ++I) { Val &T = Arr[I]; int Y = T.X; int Z = Arr[I].X + T.X; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : Arr) // CHECK-FIXES-NEXT: Val &T = I; // CHECK-FIXES-NEXT: int Y = T.X; // CHECK-FIXES-NEXT: int Z = I.X + T.X; for (int I = 0; I < N; ++I) { Val T = Arr[I]; int Y = T.X; int Z = Arr[I].X + T.X; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : Arr) // CHECK-FIXES-NEXT: Val T = I; // CHECK-FIXES-NEXT: int Y = T.X; // CHECK-FIXES-NEXT: int Z = I.X + T.X; // The same for pseudo-arrays like std::vector<T> (or here dependent<Val>) // which provide a subscript operator[]. for (int I = 0; I < V.size(); ++I) { Val &T = V[I]; {} int Y = T.X; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & T : V) // CHECK-FIXES-NEXT: {} // CHECK-FIXES-NEXT: int Y = T.X; // The same with a call to at() for (int I = 0; I < Pv->size(); ++I) { Val &T = Pv->at(I); {} int Y = T.X; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & T : *Pv) // CHECK-FIXES-NEXT: {} // CHECK-FIXES-NEXT: int Y = T.X; for (int I = 0; I < N; ++I) { Val &T = func(Arr[I]); int Y = T.X; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : Arr) // CHECK-FIXES-NEXT: Val &T = func(I); // CHECK-FIXES-NEXT: int Y = T.X; int IntArr[N]; for (unsigned I = 0; I < N; ++I) { if (int Alias = IntArr[I]) { sideEffect(Alias); } } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Alias : IntArr) // CHECK-FIXES-NEXT: if (Alias) for (unsigned I = 0; I < N; ++I) { while (int Alias = IntArr[I]) { sideEffect(Alias); } } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Alias : IntArr) // CHECK-FIXES-NEXT: while (Alias) for (unsigned I = 0; I < N; ++I) { switch (int Alias = IntArr[I]) { default: sideEffect(Alias); } } // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Alias : IntArr) // CHECK-FIXES-NEXT: switch (Alias) for (unsigned I = 0; I < N; ++I) { for (int Alias = IntArr[I]; Alias < N; ++Alias) { sideEffect(Alias); } } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Alias : IntArr) // CHECK-FIXES-NEXT: for (; Alias < N; ++Alias) for (unsigned I = 0; I < N; ++I) { for (unsigned J = 0; int Alias = IntArr[I]; ++J) { sideEffect(Alias); } } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Alias : IntArr) // CHECK-FIXES-NEXT: for (unsigned J = 0; Alias; ++J) struct IntRef { IntRef(); IntRef(const int& i); operator int*(); }; for (int I = 0; I < N; ++I) { IntRef Int(IntArr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : IntArr) // CHECK-FIXES-NEXT: IntRef Int(I); int *PtrArr[N]; for (unsigned I = 0; I < N; ++I) { const int* const P = PtrArr[I]; printf("%d\n", *P); } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto P : PtrArr) // CHECK-FIXES-NEXT: printf("%d\n", *P); IntRef Refs[N]; for (unsigned I = 0; I < N; ++I) { int *P = Refs[I]; printf("%d\n", *P); } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & Ref : Refs) // CHECK-FIXES-NEXT: int *P = Ref; // CHECK-FIXES-NEXT: printf("%d\n", *P); // Ensure that removing the alias doesn't leave empty lines behind. for (int I = 0; I < N; ++I) { auto &X = IntArr[I]; X = 0; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & X : IntArr) { // CHECK-FIXES-NEXT: {{^ X = 0;$}} // CHECK-FIXES-NEXT: {{^ }$}} }
void wrongEnd() { int bad; for (int i = 0, e = v.size(); i < bad; ++i) sum += v[i]; }