aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorEdwin Vane <edwin.vane@intel.com>2013-01-08 14:36:29 +0000
committerEdwin Vane <edwin.vane@intel.com>2013-01-08 14:36:29 +0000
commitf990ffe391848a23857453d901c989fb332d16a6 (patch)
tree5e61ab1f30725addd5f31ec41c611f910c130ef7 /test
parentcf2f8107d1f86f6363df00a79c575b75e9528c59 (diff)
Transferred loop-convert tests to cpp11-migrate
- Turned off -count-only tests as they aren't supported in cpp11-migrate yet. - Updated tests to use new binary name and options to access loop-convert transform. - Fixed header guards to not use restricted names. Reviewers: klimek, gribozavr git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@171852 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/cpp11-migrate/LoopConvert/Inputs/negative-header.h14
-rw-r--r--test/cpp11-migrate/LoopConvert/Inputs/structures.h140
-rw-r--r--test/cpp11-migrate/LoopConvert/array.cpp155
-rw-r--r--test/cpp11-migrate/LoopConvert/confidence.cpp35
-rw-r--r--test/cpp11-migrate/LoopConvert/dependency.cpp26
-rw-r--r--test/cpp11-migrate/LoopConvert/iterator.cpp103
-rw-r--r--test/cpp11-migrate/LoopConvert/naming.cpp67
-rw-r--r--test/cpp11-migrate/LoopConvert/negative-iterator.cpp160
-rw-r--r--test/cpp11-migrate/LoopConvert/negative-multi-end-call.cpp64
-rw-r--r--test/cpp11-migrate/LoopConvert/negative-pseudoarray-extra.cpp29
-rw-r--r--test/cpp11-migrate/LoopConvert/negative-pseudoarray.cpp129
-rw-r--r--test/cpp11-migrate/LoopConvert/negative.cpp123
-rw-r--r--test/cpp11-migrate/LoopConvert/nesting.cpp57
-rw-r--r--test/cpp11-migrate/LoopConvert/nocompile.cpp21
-rw-r--r--test/cpp11-migrate/LoopConvert/pseudoarray.cpp66
-rw-r--r--test/cpp11-migrate/LoopConvert/single-iterator.cpp115
16 files changed, 1304 insertions, 0 deletions
diff --git a/test/cpp11-migrate/LoopConvert/Inputs/negative-header.h b/test/cpp11-migrate/LoopConvert/Inputs/negative-header.h
new file mode 100644
index 00000000..3962032d
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/Inputs/negative-header.h
@@ -0,0 +1,14 @@
+#ifndef NEGATIVE_HEADER_H
+#define NEGATIVE_HEADER_H
+
+// Single FileCheck line to make sure that no loops are converted.
+// CHECK-NOT: for ({{.*[^:]:[^:].*}})
+static void loopInHeader() {
+ const int N = 10;
+ int arr[N];
+ int sum = 0;
+ for (int i = 0; i < N; ++i)
+ sum += arr[i];
+}
+
+#endif // NEGATIVE_HEADER_H
diff --git a/test/cpp11-migrate/LoopConvert/Inputs/structures.h b/test/cpp11-migrate/LoopConvert/Inputs/structures.h
new file mode 100644
index 00000000..2507b342
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/Inputs/structures.h
@@ -0,0 +1,140 @@
+#ifndef STRUCTURES_H
+#define STRUCTURES_H
+
+extern "C" {
+extern int printf(const char *restrict, ...);
+}
+
+struct Val {int x; void g(); };
+
+struct MutableVal {
+ void constFun(int) const;
+ void nonConstFun(int, int);
+ void constFun(MutableVal &) const;
+ void constParamFun(const MutableVal &) const;
+ void nonConstParamFun(const MutableVal &);
+ int x;
+};
+
+struct S {
+ typedef MutableVal *iterator;
+ typedef const MutableVal *const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+ iterator begin();
+ iterator end();
+};
+
+struct T {
+ struct iterator {
+ int& operator*();
+ const int& operator*()const;
+ iterator& operator ++();
+ bool operator!=(const iterator &other);
+ void insert(int);
+ int x;
+ };
+ iterator begin();
+ iterator end();
+};
+
+struct U {
+ struct iterator {
+ Val& operator*();
+ const Val& operator*()const;
+ iterator& operator ++();
+ bool operator!=(const iterator &other);
+ Val *operator->();
+ };
+ iterator begin();
+ iterator end();
+ int x;
+};
+
+struct X {
+ S s;
+ T t;
+ U u;
+ S getS();
+};
+
+template<typename ElemType>
+class dependent{
+ public:
+ struct iterator_base {
+ const ElemType& operator*()const;
+ iterator_base& operator ++();
+ bool operator!=(const iterator_base &other) const;
+ const ElemType *operator->() const;
+ };
+
+ struct iterator : iterator_base {
+ ElemType& operator*();
+ iterator& operator ++();
+ ElemType *operator->();
+ };
+
+ typedef iterator_base const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+ iterator begin();
+ iterator end();
+ unsigned size() const;
+ ElemType & operator[](unsigned);
+ const ElemType & operator[](unsigned) const;
+ ElemType & at(unsigned);
+ const ElemType & at(unsigned) const;
+
+ // Intentionally evil.
+ dependent<ElemType> operator*();
+
+ void foo();
+ void constFoo() const;
+};
+
+template<typename First, typename Second>
+class doublyDependent{
+ public:
+ struct Value {
+ First first;
+ Second second;
+ };
+
+ struct iterator_base {
+ const Value& operator*()const;
+ iterator_base& operator ++();
+ bool operator!=(const iterator_base &other) const;
+ const Value *operator->() const;
+ };
+
+ struct iterator : iterator_base {
+ Value& operator*();
+ Value& operator ++();
+ Value *operator->();
+ };
+
+ typedef iterator_base const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+ iterator begin();
+ iterator end();
+};
+
+template<typename Contained>
+class transparent {
+ public:
+ Contained *at();
+ Contained *operator->();
+ Contained operator*();
+};
+
+template<typename IteratorType>
+struct Nested {
+ typedef IteratorType* iterator;
+ IteratorType *operator->();
+ IteratorType operator*();
+ iterator begin();
+ iterator end();
+};
+
+#endif // STRUCTURES_H
diff --git a/test/cpp11-migrate/LoopConvert/array.cpp b/test/cpp11-migrate/LoopConvert/array.cpp
new file mode 100644
index 00000000..9e5230ed
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/array.cpp
@@ -0,0 +1,155 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cp %t.cpp %t.base
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+// RUN: cp %t.base %t.cpp
+// NORUN cpp11-migrate -count-only . %t.cpp -- -I %S/Inputs > %T/out
+// NORUN FileCheck -check-prefix=COUNTONLY -input-file=%T/out %s
+// RUN: diff %t.cpp %t.base
+
+#include "structures.h"
+
+const int N = 6;
+const int NMinusOne = N - 1;
+int arr[N] = {1, 2, 3, 4, 5, 6};
+int (*pArr)[N] = &arr;
+
+void f() {
+ int sum = 0;
+ // Update the number of correctly converted loops as this test changes:
+ // COUNTONLY: 15 converted
+ // COUNTONLY-NEXT: 0 potentially conflicting
+ // COUNTONLY-NEXT: 0 change(s) rejected
+
+ for (int i = 0; i < N; ++i) {
+ sum += arr[i];
+ int k;
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr) {
+ // CHECK-NEXT: sum += [[VAR]];
+ // CHECK-NEXT: int k;
+ // CHECK-NEXT: }
+
+ for (int i = 0; i < N; ++i) {
+ printf("Fibonacci number is %d\n", arr[i]);
+ sum += arr[i] + 2;
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+ // CHECK-NEXT: sum += [[VAR]] + 2;
+
+ for (int i = 0; i < N; ++i) {
+ int x = arr[i];
+ int y = arr[i] + 2;
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr)
+ // CHECK-NEXT: int x = [[VAR]];
+ // CHECK-NEXT: int y = [[VAR]] + 2;
+
+ for (int i = 0; i < N; ++i) {
+ int x = N;
+ x = arr[i];
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr)
+ // CHECK-NEXT: int x = N;
+ // CHECK-NEXT: x = [[VAR]];
+
+ for (int i = 0; i < N; ++i) {
+ arr[i] += 1;
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr) {
+ // CHECK-NEXT: [[VAR]] += 1;
+ // CHECK-NEXT: }
+
+ for (int i = 0; i < N; ++i) {
+ int x = arr[i] + 2;
+ arr[i] ++;
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr)
+ // CHECK-NEXT: int x = [[VAR]] + 2;
+ // CHECK-NEXT: [[VAR]] ++;
+
+ for (int i = 0; i < N; ++i) {
+ arr[i] = 4 + arr[i];
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr)
+ // CHECK-NEXT: [[VAR]] = 4 + [[VAR]];
+
+ for (int i = 0; i < NMinusOne + 1; ++i) {
+ sum += arr[i];
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr) {
+ // CHECK-NEXT: sum += [[VAR]];
+ // CHECK-NEXT: }
+
+ for (int i = 0; i < N; ++i) {
+ printf("Fibonacci number %d has address %p\n", arr[i], &arr[i]);
+ sum += arr[i] + 2;
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr)
+ // CHECK-NEXT: printf("Fibonacci number %d has address %p\n", [[VAR]], &[[VAR]]);
+ // CHECK-NEXT: sum += [[VAR]] + 2;
+
+ Val teas[N];
+ for (int i = 0; i < N; ++i) {
+ teas[i].g();
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : teas) {
+ // CHECK-NEXT: [[VAR]].g();
+ // CHECK-NEXT: }
+}
+
+struct HasArr {
+ int Arr[N];
+ Val ValArr[N];
+ void implicitThis() {
+ for (int i = 0; i < N; ++i) {
+ printf("%d", Arr[i]);
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : Arr) {
+ // CHECK-NEXT: printf("%d", [[VAR]]);
+ // CHECK-NEXT: }
+
+ for (int i = 0; i < N; ++i) {
+ printf("%d", ValArr[i].x);
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : ValArr) {
+ // CHECK-NEXT: printf("%d", [[VAR]].x);
+ // CHECK-NEXT: }
+ }
+
+ void explicitThis() {
+ for (int i = 0; i < N; ++i) {
+ printf("%d", this->Arr[i]);
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : this->Arr) {
+ // CHECK-NEXT: printf("%d", [[VAR]]);
+ // CHECK-NEXT: }
+
+ for (int i = 0; i < N; ++i) {
+ printf("%d", this->ValArr[i].x);
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : this->ValArr) {
+ // CHECK-NEXT: printf("%d", [[VAR]].x);
+ // CHECK-NEXT: }
+ }
+};
+
+// Loops whose bounds are value-dependent shold not be converted.
+template<int N>
+void dependentExprBound() {
+ for (int i = 0; i < N; ++i)
+ arr[i] = 0;
+ // CHECK: for (int i = 0; i < N; ++i)
+ // CHECK-NEXT: arr[i] = 0;
+}
+template void dependentExprBound<20>();
+
+void memberFunctionPointer() {
+ Val v;
+ void (Val::*mfpArr[N])(void) = { &Val::g };
+ for (int i = 0; i < N; ++i)
+ (v.*mfpArr[i])();
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : mfpArr)
+ // CHECK-NEXT: (v.*[[VAR]])();
+}
diff --git a/test/cpp11-migrate/LoopConvert/confidence.cpp b/test/cpp11-migrate/LoopConvert/confidence.cpp
new file mode 100644
index 00000000..dc229a19
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/confidence.cpp
@@ -0,0 +1,35 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+// RUN: cpp11-migrate -loop-convert %t.cpp -risk=risky -- -I %S/Inputs
+// RUN: FileCheck -check-prefix=RISKY -input-file=%t.cpp %s
+
+#include "structures.h"
+
+void f() {
+ const int N = 5;
+ const int M = 7;
+ int (*pArr)[N];
+ int Arr[N][M];
+ int sum = 0;
+
+ for (int i = 0; i < M; ++i) {
+ sum += Arr[0][i];
+ }
+ // CHECK: for (int i = 0; i < M; ++i) {
+ // CHECK-NEXT: sum += Arr[0][i];
+ // CHECK-NEXT: }
+ // RISKY: for (auto & [[VAR:[a-z_]+]] : Arr[0]) {
+ // RISKY-NEXT: sum += [[VAR]];
+ // RISKY-NEXT: }
+
+ for (int i = 0; i < N; ++i) {
+ sum += (*pArr)[i];
+ }
+ // RISKY: for (auto & [[VAR:[a-z_]+]] : *pArr) {
+ // RISKY-NEXT: sum += [[VAR]];
+ // RISKY-NEXT: }
+ // CHECK: for (int i = 0; i < N; ++i) {
+ // CHECK-NEXT: sum += (*pArr)[i];
+ // CHECK-NEXT: }
+}
diff --git a/test/cpp11-migrate/LoopConvert/dependency.cpp b/test/cpp11-migrate/LoopConvert/dependency.cpp
new file mode 100644
index 00000000..d1cec3f9
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/dependency.cpp
@@ -0,0 +1,26 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- && FileCheck -input-file=%t.cpp %s
+
+void f() {
+ const int N = 6;
+ const int M = 8;
+ int arr[N][M];
+
+ for (int i = 0; i < N; ++i) {
+ int a = 0;
+ int b = arr[i][a];
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : arr) {
+ // CHECK-NEXT: int a = 0;
+ // CHECK-NEXT: int b = [[VAR]][a];
+ // CHECK-NEXT: }
+
+ for (int j = 0; j < M; ++j) {
+ int a = 0;
+ int b = arr[a][j];
+ }
+ // CHECK: for (int j = 0; j < M; ++j) {
+ // CHECK-NEXT: int a = 0;
+ // CHECK-NEXT: int b = arr[a][j];
+ // CHECK-NEXT: }
+}
diff --git a/test/cpp11-migrate/LoopConvert/iterator.cpp b/test/cpp11-migrate/LoopConvert/iterator.cpp
new file mode 100644
index 00000000..24981edd
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/iterator.cpp
@@ -0,0 +1,103 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+
+#include "structures.h"
+
+void f() {
+ /// begin()/end() - based for loops here:
+ T t;
+ for (T::iterator it = t.begin(), e = t.end(); it != e; ++it) {
+ printf("I found %d\n", *it);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]+&? ?}}[[VAR:[a-z_]+]] : t)
+ // CHECK-NEXT: printf("I found %d\n", [[VAR]]);
+
+ T *pt;
+ for (T::iterator it = pt->begin(), e = pt->end(); it != e; ++it) {
+ printf("I found %d\n", *it);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]+&? ?}}[[VAR:[a-z_]+]] : *pt)
+ // CHECK-NEXT: printf("I found %d\n", [[VAR]]);
+
+ S s;
+ for (S::const_iterator it = s.begin(), e = s.end(); it != e; ++it) {
+ printf("s has value %d\n", (*it).x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: printf("s has value %d\n", ([[VAR]]).x);
+
+ S *ps;
+ for (S::const_iterator it = ps->begin(), e = ps->end(); it != e; ++it) {
+ printf("s has value %d\n", (*it).x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : *ps)
+ // CHECK-NEXT: printf("s has value %d\n", ([[VAR]]).x);
+
+ for (S::const_iterator it = s.begin(), e = s.end(); it != e; ++it) {
+ printf("s has value %d\n", it->x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: printf("s has value %d\n", [[VAR]].x);
+
+ for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
+ it->x = 3;
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: [[VAR]].x = 3;
+
+ for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
+ (*it).x = 3;
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: ([[VAR]]).x = 3;
+
+ for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
+ it->nonConstFun(4, 5);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: [[VAR]].nonConstFun(4, 5);
+
+ U u;
+ for (U::iterator it = u.begin(), e = u.end(); it != e; ++it) {
+ printf("s has value %d\n", it->x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : u)
+ // CHECK-NEXT: printf("s has value %d\n", [[VAR]].x);
+
+ for (U::iterator it = u.begin(), e = u.end(); it != e; ++it) {
+ printf("s has value %d\n", (*it).x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : u)
+ // CHECK-NEXT: printf("s has value %d\n", ([[VAR]]).x);
+
+ U::iterator A;
+ for (U::iterator i = u.begin(), e = u.end(); i != e; ++i)
+ int k = A->x + i->x;
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : u)
+ // CHECK-NEXT: int k = A->x + [[VAR]].x;
+
+ dependent<int> v;
+ for (dependent<int>::const_iterator it = v.begin(), e = v.end();
+ it != e; ++it) {
+ printf("Fibonacci number is %d\n", *it);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : v)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+
+ for (dependent<int>::const_iterator it(v.begin()), e = v.end();
+ it != e; ++it) {
+ printf("Fibonacci number is %d\n", *it);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : v)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+
+ doublyDependent<int,int> intmap;
+ for (doublyDependent<int,int>::iterator it = intmap.begin(), e = intmap.end();
+ it != e; ++it) {
+ printf("intmap[%d] = %d", it->first, it->second);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : intmap)
+ // CHECK-NEXT: printf("intmap[%d] = %d", [[VAR]].first, [[VAR]].second);
+
+}
diff --git a/test/cpp11-migrate/LoopConvert/naming.cpp b/test/cpp11-migrate/LoopConvert/naming.cpp
new file mode 100644
index 00000000..f232af1f
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/naming.cpp
@@ -0,0 +1,67 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+
+#include "structures.h"
+
+const int N = 10;
+int nums[N];
+int sum = 0;
+
+Val Arr[N];
+Val &func(Val &);
+
+void aliasing() {
+ // 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-NEXT: { }
+ // CHECK-NEXT: int y = 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 & [[VAR:[a-z_]+]] : Arr)
+ // CHECK-NEXT: Val &t = [[VAR]];
+ // CHECK-NEXT: int y = t.x;
+ // CHECK-NEXT: int z = [[VAR]].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 & [[VAR:[a-z_]+]] : Arr)
+ // CHECK-NEXT: Val t = [[VAR]];
+ // CHECK-NEXT: int y = t.x;
+ // CHECK-NEXT: int z = [[VAR]].x + t.x;
+
+ for (int i = 0; i < N; ++i) {
+ Val &t = func(Arr[i]);
+ int y = t.x;
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : Arr)
+ // CHECK-NEXT: Val &t = func([[VAR]]);
+ // CHECK-NEXT: int y = t.x;
+}
+
+void sameNames() {
+ int num = 0;
+ for (int i = 0; i < N; ++i) {
+ printf("Fibonacci number is %d\n", nums[i]);
+ sum += nums[i] + 2 + num;
+ (void) nums[i];
+ }
+ // CHECK: int num = 0;
+ // CHECK-NEXT: for (auto & [[VAR:[a-z_]+]] : nums)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+ // CHECK-NEXT: sum += [[VAR]] + 2 + num;
+ // CHECK-NOT: (void) num;
+ // CHECK: }
+}
diff --git a/test/cpp11-migrate/LoopConvert/negative-iterator.cpp b/test/cpp11-migrate/LoopConvert/negative-iterator.cpp
new file mode 100644
index 00000000..09c43476
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/negative-iterator.cpp
@@ -0,0 +1,160 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+
+#include "structures.h"
+
+// Single FileCheck line to make sure that no loops are converted.
+// CHECK-NOT: for ({{.*[^:]:[^:].*}})
+
+S s;
+T t;
+U u;
+
+struct BadBeginEnd : T {
+ iterator notBegin();
+ iterator notEnd();
+};
+
+void notBeginOrEnd() {
+ BadBeginEnd Bad;
+ for (T::iterator i = Bad.notBegin(), e = Bad.end(); i != e; ++i)
+ int k = *i;
+
+ for (T::iterator i = Bad.begin(), e = Bad.notEnd(); i != e; ++i)
+ int k = *i;
+}
+
+void badLoopShapes() {
+ for (T::iterator i = t.begin(), e = t.end(), f = e; i != e; ++i)
+ int k = *i;
+
+ for (T::iterator i = t.begin(), e = t.end(); i != e; )
+ int k = *i;
+
+ for (T::iterator i = t.begin(), e = t.end(); ; ++i)
+ int k = *i;
+
+ T::iterator outsideI;
+ T::iterator outsideE;
+
+ for (; outsideI != outsideE ; ++outsideI)
+ int k = *outsideI;
+}
+
+void iteratorArrayMix() {
+ int lower;
+ const int N = 6;
+ for (T::iterator i = t.begin(), e = t.end(); lower < N; ++i)
+ int k = *i;
+
+ for (T::iterator i = t.begin(), e = t.end(); lower < N; ++lower)
+ int k = *i;
+}
+
+struct ExtraConstructor : T::iterator {
+ ExtraConstructor(T::iterator, int);
+ explicit ExtraConstructor(T::iterator);
+};
+
+void badConstructor() {
+ for (T::iterator i = ExtraConstructor(t.begin(), 0), e = t.end();
+ i != e; ++i)
+ int k = *i;
+ for (T::iterator i = ExtraConstructor(t.begin()), e = t.end(); i != e; ++i)
+ int k = *i;
+}
+
+void iteratorMemberUsed() {
+ for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
+ i.x = *i;
+
+ for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
+ int k = i.x + *i;
+
+ for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
+ int k = e.x + *i;
+}
+
+void iteratorMethodCalled() {
+ for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
+ i.insert(3);
+
+ for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
+ if (i != i)
+ int k = 3;
+}
+
+void iteratorOperatorCalled() {
+ for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
+ int k = *(++i);
+
+ for (S::iterator i = s.begin(), e = s.end(); i != e; ++i)
+ MutableVal k = *(++i);
+}
+
+void differentContainers() {
+ T other;
+ for (T::iterator i = t.begin(), e = other.end(); i != e; ++i)
+ int k = *i;
+
+ for (T::iterator i = other.begin(), e = t.end(); i != e; ++i)
+ int k = *i;
+
+ S otherS;
+ for (S::iterator i = s.begin(), e = otherS.end(); i != e; ++i)
+ MutableVal k = *i;
+
+ for (S::iterator i = otherS.begin(), e = s.end(); i != e; ++i)
+ MutableVal k = *i;
+}
+
+void wrongIterators() {
+ T::iterator other;
+ for (T::iterator i = t.begin(), e = t.end(); i != other; ++i)
+ int k = *i;
+}
+
+struct EvilArrow : U {
+ // Please, no one ever write code like this.
+ U* operator->();
+};
+
+void differentMemberAccessTypes() {
+ EvilArrow A;
+ for (EvilArrow::iterator i = A.begin(), e = A->end(); i != e; ++i)
+ Val k = *i;
+ for (EvilArrow::iterator i = A->begin(), e = A.end(); i != e; ++i)
+ Val k = *i;
+}
+
+void f(const T::iterator &it, int);
+void f(const T &it, int);
+void g(T &it, int);
+
+void iteratorPassedToFunction() {
+ for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
+ f(i, *i);
+}
+
+// FIXME: Disallow this except for containers passed by value and/or const
+// reference. Or maybe this is correct enough for any container?
+void containerPassedToFunction() {
+// for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
+// f(t, *i);
+// for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
+// g(t, *i);
+}
+
+// FIXME: These tests can be removed if this tool ever does enough analysis to
+// decide that this is a safe transformation.
+// Until then, we don't want it applied.
+void iteratorDefinedOutside() {
+ T::iterator theEnd = t.end();
+ for (T::iterator i = t.begin(); i != theEnd; ++i)
+ int k = *i;
+
+ T::iterator theBegin = t.begin();
+ for (T::iterator e = t.end(); theBegin != e; ++theBegin)
+ int k = *theBegin;
+}
diff --git a/test/cpp11-migrate/LoopConvert/negative-multi-end-call.cpp b/test/cpp11-migrate/LoopConvert/negative-multi-end-call.cpp
new file mode 100644
index 00000000..6e50ee72
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/negative-multi-end-call.cpp
@@ -0,0 +1,64 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert -risk=safe %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+
+#include "structures.h"
+
+// Single FileCheck line to make sure that no loops are converted.
+// CHECK-NOT: for ({{.*[^:]:[^:].*}})
+
+S s;
+T t;
+U u;
+
+void multipleEnd() {
+ for (S::iterator i = s.begin(); i != s.end(); ++i)
+ MutableVal k = *i;
+
+ for (T::iterator i = t.begin(); i != t.end(); ++i)
+ int k = *i;
+
+ for (U::iterator i = u.begin(); i != u.end(); ++i)
+ Val k = *i;
+}
+
+void f(X);
+void f(S);
+void f(T);
+
+void complexContainer() {
+ X x;
+ for (S::iterator i = x.s.begin(), e = x.s.end(); i != e; ++i) {
+ f(x);
+ MutableVal k = *i;
+ }
+
+ for (T::iterator i = x.t.begin(), e = x.t.end(); i != e; ++i) {
+ f(x);
+ int k = *i;
+ }
+
+ for (S::iterator i = x.s.begin(), e = x.s.end(); i != e; ++i) {
+ f(x.s);
+ MutableVal k = *i;
+ }
+
+ for (T::iterator i = x.t.begin(), e = x.t.end(); i != e; ++i) {
+ f(x.t);
+ int k = *i;
+ }
+
+ for (S::iterator i = x.getS().begin(), e = x.getS().end(); i != e; ++i) {
+ f(x.getS());
+ MutableVal k = *i;
+ }
+
+ X exes[5];
+ int index = 0;
+
+ for (S::iterator i = exes[index].getS().begin(),
+ e = exes[index].getS().end(); i != e; ++i) {
+ index++;
+ MutableVal k = *i;
+ }
+}
diff --git a/test/cpp11-migrate/LoopConvert/negative-pseudoarray-extra.cpp b/test/cpp11-migrate/LoopConvert/negative-pseudoarray-extra.cpp
new file mode 100644
index 00000000..3ccdb12c
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/negative-pseudoarray-extra.cpp
@@ -0,0 +1,29 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+
+#include "structures.h"
+
+// Single FileCheck line to make sure that no loops are converted.
+// CHECK-NOT: for ({{.*[^:]:[^:].*}})
+
+const int N = 6;
+dependent<int> v;
+dependent<int> *pv;
+
+int sum = 0;
+
+// 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();
+ }
+}
diff --git a/test/cpp11-migrate/LoopConvert/negative-pseudoarray.cpp b/test/cpp11-migrate/LoopConvert/negative-pseudoarray.cpp
new file mode 100644
index 00000000..cbc67be2
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/negative-pseudoarray.cpp
@@ -0,0 +1,129 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+
+#include "structures.h"
+
+// Single FileCheck line to make sure that no loops are converted.
+// CHECK-NOT: for ({{.*[^:]:[^:].*}})
+
+const int N = 6;
+dependent<int> v;
+dependent<int> *pv;
+
+transparent<dependent<int> > cv;
+int sum = 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];
+}
+
+// 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 ++;
+}
+
+// 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;
+}
+
+// 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 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;
+ }
+}
+
+// Check to make sure that dereferenced pointers-to-containers behave nicely
+void derefContainer() {
+ // Note the dependent<T>::operator*() returns another dependent<T>.
+ // This test makes sure that we don't allow an arbitrary number of *'s.
+ for (int i = 0; i < pv->size(); ++i)
+ sum += (**pv).at(i);
+
+ for (int i = 0; i < pv->size(); ++i)
+ sum += (**pv)[i];
+}
+
+void wrongEnd() {
+ int bad;
+ for (int i = 0, e = v.size(); i < bad; ++i)
+ sum += v[i];
+}
diff --git a/test/cpp11-migrate/LoopConvert/negative.cpp b/test/cpp11-migrate/LoopConvert/negative.cpp
new file mode 100644
index 00000000..0075f5ea
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/negative.cpp
@@ -0,0 +1,123 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/negative-header.h > \
+// RUN: %T/negative-header.h
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs/
+// RUN: FileCheck -input-file=%t.cpp %s
+// RUN: FileCheck -input-file=%T/negative-header.h %S/Inputs/negative-header.h
+
+#include "negative-header.h"
+#include "structures.h"
+
+// Single FileCheck line to make sure that no loops are converted.
+// CHECK-NOT: for ({{.*[^:]:[^:].*}})
+
+const int N = 6;
+int arr[N] = {1, 2, 3, 4, 5, 6};
+int (*pArr)[N] = &arr;
+int sum = 0;
+
+// Checks for the index start and end:
+void indexStartAndEnd() {
+ for (int i = 0; i < N + 1; ++i)
+ sum += arr[i];
+
+ for (int i = 0; i < N - 1; ++i)
+ sum += arr[i];
+
+ for (int i = 1; i < N; ++i)
+ sum += arr[i];
+
+ for (int i = 1; i < N; ++i)
+ sum += arr[i];
+
+ for (int i = 0; ; ++i)
+ sum += (*pArr)[i];
+}
+
+// Checks for invalid increment steps:
+void increment() {
+ for (int i = 0; i < N; --i)
+ sum += arr[i];
+
+ for (int i = 0; i < N; i)
+ sum += arr[i];
+
+ for (int i = 0; i < N;)
+ sum += arr[i];
+
+ for (int i = 0; i < N; i += 2)
+ sum ++;
+}
+
+// Checks to make sure that the index isn't used outside of the array:
+void indexUse() {
+ for (int i = 0; i < N; ++i)
+ arr[i] += 1 + i;
+}
+
+// Check for loops that don't mention arrays
+void noArray() {
+ for (int i = 0; i < N; ++i)
+ sum += i;
+
+ for (int i = 0; i < N; ++i) { }
+
+ for (int i = 0; i < N; ++i) ;
+}
+
+// Checks for incorrect loop variables.
+void mixedVariables() {
+ int badIndex;
+ for (int i = 0; badIndex < N; ++i)
+ sum += arr[i];
+
+ for (int i = 0; i < N; ++badIndex)
+ sum += arr[i];
+
+ for (int i = 0; badIndex < N; ++badIndex)
+ sum += arr[i];
+
+ for (int i = 0; badIndex < N; ++badIndex)
+ sum += arr[badIndex];
+}
+
+// Checks for multiple arrays indexed.
+void multipleArrays() {
+ int badArr[N];
+
+ for (int i = 0; i < N; ++i)
+ sum += arr[i] + badArr[i];
+
+ for (int i = 0; i < N; ++i) {
+ int k = badArr[i];
+ sum += arr[i] + k;
+ }
+}
+
+struct HasArr {
+ int Arr[N];
+ Val ValArr[N];
+};
+
+struct HasIndirectArr {
+ HasArr HA;
+ void implicitThis() {
+ for (int i = 0; i < N; ++i) {
+ printf("%d", HA.Arr[i]);
+ }
+
+ for (int i = 0; i < N; ++i) {
+ printf("%d", HA.ValArr[i].x);
+ }
+ }
+
+ void explicitThis() {
+ for (int i = 0; i < N; ++i) {
+ printf("%d", this->HA.Arr[i]);
+ }
+
+ for (int i = 0; i < N; ++i) {
+ printf("%d", this->HA.ValArr[i].x);
+ }
+ }
+};
diff --git a/test/cpp11-migrate/LoopConvert/nesting.cpp b/test/cpp11-migrate/LoopConvert/nesting.cpp
new file mode 100644
index 00000000..588362aa
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/nesting.cpp
@@ -0,0 +1,57 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+
+#include "structures.h"
+
+void f() {
+ const int N = 10;
+ const int M = 15;
+ Val Arr[N];
+ for (int i = 0; i < N; ++i) {
+ for (int j = 0; j < N; ++j) {
+ int k = Arr[i].x + Arr[j].x;
+ // The repeat is there to allow FileCheck to make sure the two variable
+ // names aren't the same.
+ int l = Arr[i].x + Arr[j].x;
+ }
+ }
+ // CHECK: for (auto & [[VAR:[a-zA-Z_]+]] : Arr)
+ // CHECK-NEXT: for (auto & [[INNERVAR:[a-zA-Z_]+]] : Arr)
+ // CHECK-NEXT: int k = [[VAR]].x + [[INNERVAR]].x;
+ // CHECK-NOT: int l = [[VAR]].x + [[VAR]].x;
+
+ Val Nest[N][M];
+ for (int i = 0; i < N; ++i) {
+ for (int j = 0; j < M; ++j) {
+ printf("Got item %d", Nest[i][j].x);
+ }
+ }
+ // The inner loop is also convertible, but doesn't need to be converted
+ // immediately. Update this test when that changes!
+ // CHECK: for (auto & [[VAR:[a-zA-Z_]+]] : Nest)
+ // CHECK-NEXT: for (int j = 0; j < M; ++j)
+ // CHECK-NEXT: printf("Got item %d", [[VAR]][j].x);
+
+ // Note that the order of M and N are switched for this test.
+ for (int j = 0; j < M; ++j) {
+ for (int i = 0; i < N; ++i) {
+ printf("Got item %d", Nest[i][j].x);
+ }
+ }
+ // CHECK-NOT: for (auto & {{[a-zA-Z_]+}} : Nest[i])
+ // CHECK: for (int j = 0; j < M; ++j)
+ // CHECK-NEXT: for (auto & [[VAR:[a-zA-Z_]+]] : Nest)
+ // CHECK-NEXT: printf("Got item %d", [[VAR]][j].x);
+ Nested<T> NestT;
+ for (Nested<T>::iterator I = NestT.begin(), E = NestT.end(); I != E; ++I) {
+ for (T::iterator TI = (*I).begin(), TE = (*I).end(); TI != TE; ++TI) {
+ printf("%d", *TI);
+ }
+ }
+ // The inner loop is also convertible, but doesn't need to be converted
+ // immediately. Update this test when that changes!
+ // CHECK: for (auto & [[VAR:[a-zA-Z_]+]] : NestT) {
+ // CHECK-NEXT: for (T::iterator TI = ([[VAR]]).begin(), TE = ([[VAR]]).end(); TI != TE; ++TI) {
+ // CHECK-NEXT: printf("%d", *TI);
+}
diff --git a/test/cpp11-migrate/LoopConvert/nocompile.cpp b/test/cpp11-migrate/LoopConvert/nocompile.cpp
new file mode 100644
index 00000000..ea102877
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/nocompile.cpp
@@ -0,0 +1,21 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: not cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+
+void valid() {
+ const int arr[5];
+ int sum = 0;
+ for (int i = 0; i < 5; ++i) {
+ sum += arr[i];
+ }
+}
+void hasSyntaxError = 3;
+// CHECK: void valid() {
+// CHECK-NEXT: const int arr[5];
+// CHECK-NEXT: int sum = 0;
+// CHECK-NEXT: for (int i = 0; i < 5; ++i) {
+// CHECK-NEXT: sum += arr[i];
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+
+// CHECK-NEXT: void hasSyntaxError = 3;
diff --git a/test/cpp11-migrate/LoopConvert/pseudoarray.cpp b/test/cpp11-migrate/LoopConvert/pseudoarray.cpp
new file mode 100644
index 00000000..e4f159fb
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/pseudoarray.cpp
@@ -0,0 +1,66 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+#include "structures.h"
+
+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: for (auto & [[VAR:[a-z_]+]] : v)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+ // CHECK-NEXT: sum += [[VAR]] + 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: for (auto & [[VAR:[a-z_]+]] : v)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+ // CHECK-NEXT: sum += [[VAR]] + 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: for (auto & [[VAR:[a-z_]+]] : *pv)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+ // CHECK-NEXT: sum += [[VAR]] + 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: for (auto & [[VAR:[a-z_]+]] : *pv)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+ // CHECK-NEXT: sum += [[VAR]] + 2;
+
+ for (int i = 0; i < cv->size(); ++i) {
+ printf("Fibonacci number is %d\n", cv->at(i));
+ sum += cv->at(i) + 2;
+ }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : *cv)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+ // CHECK-NEXT: sum += [[VAR]] + 2;
+}
+
+// Check for loops that don't mention containers
+void noContainer() {
+ for (auto i = 0; i < v.size(); ++i) { }
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : v) { }
+
+ for (auto i = 0; i < v.size(); ++i) ;
+ // CHECK: for (auto & [[VAR:[a-z_]+]] : v) ;
+}
diff --git a/test/cpp11-migrate/LoopConvert/single-iterator.cpp b/test/cpp11-migrate/LoopConvert/single-iterator.cpp
new file mode 100644
index 00000000..fa7e14eb
--- /dev/null
+++ b/test/cpp11-migrate/LoopConvert/single-iterator.cpp
@@ -0,0 +1,115 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+
+#include "structures.h"
+
+void complexContainer() {
+ X exes[5];
+ int index = 0;
+
+ for (S::iterator i = exes[index].getS().begin(), e = exes[index].getS().end(); i != e; ++i) {
+ MutableVal k = *i;
+ MutableVal j = *i;
+ }
+ // CHECK: for ({{[a-zA-Z_ ]+&? ?}}[[VAR:[a-z_]+]] : exes[index].getS())
+ // CHECK-NEXT: MutableVal k = [[VAR]];
+ // CHECK-NEXT: MutableVal j = [[VAR]];
+}
+
+void f() {
+ /// begin()/end() - based for loops here:
+ T t;
+ for (T::iterator it = t.begin(); it != t.end(); ++it) {
+ printf("I found %d\n", *it);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]+&? ?}}[[VAR:[a-z_]+]] : t)
+ // CHECK-NEXT: printf("I found %d\n", [[VAR]]);
+
+ T *pt;
+ for (T::iterator it = pt->begin(); it != pt->end(); ++it) {
+ printf("I found %d\n", *it);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]+&? ?}}[[VAR:[a-z_]+]] : *pt)
+ // CHECK-NEXT: printf("I found %d\n", [[VAR]]);
+
+ S s;
+ for (S::const_iterator it = s.begin(); it != s.end(); ++it) {
+ printf("s has value %d\n", (*it).x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: printf("s has value %d\n", ([[VAR]]).x);
+
+ S *ps;
+ for (S::const_iterator it = ps->begin(); it != ps->end(); ++it) {
+ printf("s has value %d\n", (*it).x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : *ps)
+ // CHECK-NEXT: printf("s has value %d\n", ([[VAR]]).x);
+
+ for (S::const_iterator it = s.begin(); it != s.end(); ++it) {
+ printf("s has value %d\n", it->x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: printf("s has value %d\n", [[VAR]].x);
+
+ for (S::iterator it = s.begin(); it != s.end(); ++it) {
+ it->x = 3;
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: [[VAR]].x = 3;
+
+ for (S::iterator it = s.begin(); it != s.end(); ++it) {
+ (*it).x = 3;
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: ([[VAR]]).x = 3;
+
+ for (S::iterator it = s.begin(); it != s.end(); ++it) {
+ it->nonConstFun(4, 5);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : s)
+ // CHECK-NEXT: [[VAR]].nonConstFun(4, 5);
+
+ U u;
+ for (U::iterator it = u.begin(); it != u.end(); ++it) {
+ printf("s has value %d\n", it->x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : u)
+ // CHECK-NEXT: printf("s has value %d\n", [[VAR]].x);
+
+ for (U::iterator it = u.begin(); it != u.end(); ++it) {
+ printf("s has value %d\n", (*it).x);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : u)
+ // CHECK-NEXT: printf("s has value %d\n", ([[VAR]]).x);
+
+ U::iterator A;
+ for (U::iterator i = u.begin(); i != u.end(); ++i)
+ int k = A->x + i->x;
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : u)
+ // CHECK-NEXT: int k = A->x + [[VAR]].x;
+
+ dependent<int> v;
+ for (dependent<int>::const_iterator it = v.begin();
+ it != v.end(); ++it) {
+ printf("Fibonacci number is %d\n", *it);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : v)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+
+ for (dependent<int>::const_iterator it(v.begin());
+ it != v.end(); ++it) {
+ printf("Fibonacci number is %d\n", *it);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : v)
+ // CHECK-NEXT: printf("Fibonacci number is %d\n", [[VAR]]);
+
+ doublyDependent<int,int> intmap;
+ for (doublyDependent<int,int>::iterator it = intmap.begin();
+ it != intmap.end(); ++it) {
+ printf("intmap[%d] = %d", it->first, it->second);
+ }
+ // CHECK: for ({{[a-zA-Z_ ]*&? ?}}[[VAR:[a-z_]+]] : intmap)
+ // CHECK-NEXT: printf("intmap[%d] = %d", [[VAR]].first, [[VAR]].second);
+}