// 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) ; }
// 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 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(); } }
// 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 (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; }
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; }
// 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]; }
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; }
// 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 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); }
namespace NamingAlias { const int N = 10; Val Arr[N]; dependent<Val> v; dependent<Val> *pv; Val &func(Val &); void sideEffect(int); 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); } void refs_and_vals() { // The following tests check that the transform correctly preserves the // reference or value qualifiers of the aliased variable. That is, if the // variable was declared as a value, the loop variable will be declared as a // value and vice versa for references. S s; const S s_const = s; for (S::const_iterator it = s_const.begin(); it != s_const.end(); ++it) { MutableVal alias = *it; {} alias.x = 0; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto alias : s_const) // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} = // CHECK-FIXES: {} // CHECK-FIXES-NEXT: alias.x = 0; for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) { MutableVal alias = *it; {} alias.x = 0; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto alias : s) // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} = // CHECK-FIXES: {} // CHECK-FIXES-NEXT: alias.x = 0; for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) { MutableVal &alias = *it; {} alias.x = 0; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & alias : s) // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} = // CHECK-FIXES: {} // CHECK-FIXES-NEXT: alias.x = 0; dependent<int> dep, other; for (dependent<int>::iterator it = dep.begin(), e = dep.end(); it != e; ++it) { printf("%d\n", *it); const int& idx = other[0]; unsigned othersize = other.size(); } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & elem : dep) // CHECK-FIXES-NEXT: printf("%d\n", elem); // CHECK-FIXES-NEXT: const int& idx = other[0]; // CHECK-FIXES-NEXT: unsigned othersize = other.size(); for (int i = 0, e = dep.size(); i != e; ++i) { int idx = other.at(i); } } } // namespace NamingAlias
namespace PseudoArray { const int N = 6; dependent<int> V; dependent<int> *Pv; const dependent<NonTriviallyCopyable> Constv; const dependent<NonTriviallyCopyable> *Pconstv; transparent<dependent<int>> Cv; 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; } // 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; } // 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) ; } struct NoBeginEnd { unsigned size() const; unsigned& operator[](int); const unsigned& operator[](int) const; }; struct NoConstBeginEnd { NoConstBeginEnd(); unsigned size() const; unsigned* begin(); unsigned* end(); unsigned& operator[](int); const unsigned& operator[](int) const; }; struct ConstBeginEnd { ConstBeginEnd(); unsigned size() const; unsigned* begin() const; unsigned* end() const; unsigned& operator[](int); const unsigned& operator[](int) const; }; // Shouldn't transform pseudo-array uses if the container doesn't provide // begin() and end() of the right const-ness. void NoBeginEndTest() { NoBeginEnd NBE; for (unsigned I = 0, E = NBE.size(); I < E; ++I) printf("%d\n", NBE[I]); const NoConstBeginEnd Const_NCBE; for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I) printf("%d\n", Const_NCBE[I]); ConstBeginEnd CBE; for (unsigned I = 0, E = CBE.size(); I < E; ++I) printf("%d\n", CBE[I]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned int Elem : CBE) // CHECK-FIXES-NEXT: printf("%d\n", Elem); const ConstBeginEnd Const_CBE; for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I) printf("%d\n", Const_CBE[I]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned int Elem : Const_CBE) // CHECK-FIXES-NEXT: printf("%d\n", Elem); } struct DerefByValue { DerefByValue(); struct iter { unsigned operator*(); }; unsigned size() const; iter begin(); iter end(); unsigned operator[](int); }; void derefByValueTest() { DerefByValue DBV; for (unsigned I = 0, E = DBV.size(); I < E; ++I) { printf("%d\n", DBV[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned int Elem : DBV) // CHECK-FIXES-NEXT: printf("%d\n", Elem); for (unsigned I = 0, E = DBV.size(); I < E; ++I) { auto f = [DBV, I]() {}; printf("%d\n", DBV[I]); } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned int Elem : DBV) // CHECK-FIXES-NEXT: auto f = [DBV, &Elem]() {}; // CHECK-FIXES-NEXT: printf("%d\n", Elem); } void fundamentalTypesTest() { const int N = 10; bool Bools[N]; for (int i = 0; i < N; ++i) printf("%d", Bools[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (bool Bool : Bools) int Ints[N]; unsigned short int Shorts[N]; for (int i = 0; i < N; ++i) printf("%d", Shorts[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned short Short : Shorts) signed long Longs[N]; for (int i = 0; i < N; ++i) printf("%d", Longs[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (long Long : Longs) long long int LongLongs[N]; for (int i = 0; i < N; ++i) printf("%d", LongLongs[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (long long LongLong : LongLongs) char Chars[N]; for (int i = 0; i < N; ++i) printf("%d", Chars[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (char Char : Chars) wchar_t WChars[N]; for (int i = 0; i < N; ++i) printf("%d", WChars[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (wchar_t WChar : WChars) float Floats[N]; for (int i = 0; i < N; ++i) printf("%d", Floats[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (float Float : Floats) double Doubles[N]; for (int i = 0; i < N; ++i) printf("%d", Doubles[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (double Double : Doubles) } } // namespace PseudoArray
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: {{^ }$}} }
namespace NamingAlias { const int N = 10; Val Arr[N]; dependent<Val> V; dependent<Val> *Pv; Val &func(Val &); void sideEffect(int); 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 refs_and_vals() { // The following tests check that the transform correctly preserves the // reference or value qualifiers of the aliased variable. That is, if the // variable was declared as a value, the loop variable will be declared as a // value and vice versa for references. S Ss; const S S_const = Ss; for (S::const_iterator It = S_const.begin(); It != S_const.end(); ++It) { MutableVal Alias = *It; {} Alias.X = 0; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto Alias : S_const) // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} = // CHECK-FIXES-NEXT: {} // CHECK-FIXES-NEXT: Alias.X = 0; for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { MutableVal Alias = *It; {} Alias.X = 0; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto Alias : Ss) // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} = // CHECK-FIXES-NEXT: {} // CHECK-FIXES-NEXT: Alias.X = 0; for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { MutableVal &Alias = *It; {} Alias.X = 0; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & Alias : Ss) // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} = // CHECK-FIXES-NEXT: {} // CHECK-FIXES-NEXT: Alias.X = 0; dependent<int> Dep, Other; for (dependent<int>::iterator It = Dep.begin(), E = Dep.end(); It != E; ++It) { printf("%d\n", *It); const int& Idx = Other[0]; unsigned Othersize = Other.size(); } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & It : Dep) // CHECK-FIXES-NEXT: printf("%d\n", It); // CHECK-FIXES-NEXT: const int& Idx = Other[0]; // CHECK-FIXES-NEXT: unsigned Othersize = Other.size(); for (int I = 0, E = Dep.size(); I != E; ++I) { int Idx = Other.at(I); } } struct MemberNaming { const static int N = 10; int Ints[N], Ints_[N]; dependent<int> DInts; 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 outOfLine(); }; void MemberNaming::outOfLine() { for (int I = 0; I < N; ++I) { printf("%d\n", Ints[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: 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]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int Int : Ints_) // CHECK-FIXES-NEXT: printf("%d\n", Int); } } // namespace NamingAlias
// 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 wrongEnd() { int bad; for (int i = 0, e = v.size(); i < bad; ++i) sum += v[i]; }
namespace PseudoArray { const int N = 6; dependent<int> v; dependent<int> *pv; transparent<dependent<int>> cv; 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; } // 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) } struct NoBeginEnd { unsigned size() const; }; struct NoConstBeginEnd { NoConstBeginEnd(); unsigned size() const; unsigned* begin(); unsigned* end(); }; struct ConstBeginEnd { ConstBeginEnd(); unsigned size() const; unsigned* begin() const; unsigned* end() const; }; // Shouldn't transform pseudo-array uses if the container doesn't provide // begin() and end() of the right const-ness. void NoBeginEndTest() { NoBeginEnd NBE; for (unsigned i = 0, e = NBE.size(); i < e; ++i) { } const NoConstBeginEnd const_NCBE; for (unsigned i = 0, e = const_NCBE.size(); i < e; ++i) { } ConstBeginEnd CBE; for (unsigned i = 0, e = CBE.size(); i < e; ++i) { } // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & elem : CBE) { const ConstBeginEnd const_CBE; for (unsigned i = 0, e = const_CBE.size(); i < e; ++i) { } // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & elem : const_CBE) { } struct DerefByValue { DerefByValue(); struct iter { unsigned operator*(); }; unsigned size() const; iter begin(); iter end(); unsigned operator[](int); }; void derefByValueTest() { DerefByValue DBV; for (unsigned i = 0, e = DBV.size(); i < e; ++i) { printf("%d\n", DBV[i]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto elem : DBV) { // CHECK-FIXES-NEXT: printf("%d\n", elem); for (unsigned i = 0, e = DBV.size(); i < e; ++i) { auto f = [DBV, i]() {}; printf("%d\n", DBV[i]); } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto elem : DBV) { // CHECK-FIXES-NEXT: auto f = [DBV, elem]() {}; // CHECK-FIXES-NEXT: printf("%d\n", elem); } } // namespace PseudoArray