diff options
author | Edwin Vane <edwin.vane@intel.com> | 2013-01-08 14:36:29 +0000 |
---|---|---|
committer | Edwin Vane <edwin.vane@intel.com> | 2013-01-08 14:36:29 +0000 |
commit | f990ffe391848a23857453d901c989fb332d16a6 (patch) | |
tree | 5e61ab1f30725addd5f31ec41c611f910c130ef7 /test | |
parent | cf2f8107d1f86f6363df00a79c575b75e9528c59 (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.h | 14 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/Inputs/structures.h | 140 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/array.cpp | 155 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/confidence.cpp | 35 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/dependency.cpp | 26 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/iterator.cpp | 103 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/naming.cpp | 67 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/negative-iterator.cpp | 160 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/negative-multi-end-call.cpp | 64 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/negative-pseudoarray-extra.cpp | 29 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/negative-pseudoarray.cpp | 129 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/negative.cpp | 123 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/nesting.cpp | 57 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/nocompile.cpp | 21 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/pseudoarray.cpp | 66 | ||||
-rw-r--r-- | test/cpp11-migrate/LoopConvert/single-iterator.cpp | 115 |
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); +} |