forked from OSchip/llvm-project
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 llvm-svn: 171852
This commit is contained in:
parent
76c6521ba1
commit
31896624da
|
@ -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
|
|
@ -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
|
|
@ -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]])();
|
||||
}
|
|
@ -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: }
|
||||
}
|
|
@ -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: }
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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: }
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
|
@ -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) ;
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue