예제 #1
0
// 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();
  }
}
예제 #6
0
// 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;
}
예제 #9
0
// 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];
}
예제 #10
0
// 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;
}
예제 #12
0
// 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;
  }
}
예제 #13
0
// 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;
}
예제 #15
0
  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
예제 #19
0
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: {{^  }$}}
}
예제 #20
0
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
예제 #21
0
// 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;
}
예제 #22
0
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