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 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 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: for (auto & t : Arr) // CHECK-NOT: Val &{{[a-z_]+}} = // CHECK-NEXT: { } // CHECK-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: for (auto & elem : Arr) // CHECK-NEXT: Val &t = elem; // CHECK-NEXT: int y = t.x; // CHECK-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: for (auto & elem : Arr) // CHECK-NEXT: Val t = elem; // CHECK-NEXT: int y = t.x; // CHECK-NEXT: int z = elem.x + t.x; for (int i = 0; i < N; ++i) { Val &t = func(Arr[i]); int y = t.x; } // CHECK: for (auto & elem : Arr) // CHECK-NEXT: Val &t = func(elem); // CHECK-NEXT: int y = t.x; int IntArr[N]; for (unsigned i = 0; i < N; ++i) { if (int alias = IntArr[i]) { sideEffect(alias); } } // CHECK: for (auto alias : IntArr) // CHECK-NEXT: if (alias) { for (unsigned i = 0; i < N; ++i) { while (int alias = IntArr[i]) { sideEffect(alias); } } // CHECK: for (auto alias : IntArr) // CHECK-NEXT: while (alias) { for (unsigned i = 0; i < N; ++i) { switch (int alias = IntArr[i]) { default: sideEffect(alias); } } // CHECK: for (auto alias : IntArr) // CHECK-NEXT: switch (alias) { for (unsigned i = 0; i < N; ++i) { for (int alias = IntArr[i]; alias < N; ++alias) { sideEffect(alias); } } // CHECK: for (auto alias : IntArr) // CHECK-NEXT: for (; alias < N; ++alias) { for (unsigned i = 0; i < N; ++i) { for (unsigned j = 0; int alias = IntArr[i]; ++j) { sideEffect(alias); } } // CHECK: for (auto alias : IntArr) // CHECK-NEXT: for (unsigned j = 0; alias; ++j) { }