File: performance-implicit-conversion-in-loop.cpp

package info (click to toggle)
llvm-toolchain-6.0 1%3A6.0.1-10
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 598,080 kB
  • sloc: cpp: 3,046,253; ansic: 595,057; asm: 271,965; python: 128,926; objc: 106,554; sh: 21,906; lisp: 10,191; pascal: 6,094; ml: 5,544; perl: 5,265; makefile: 2,227; cs: 2,027; xml: 686; php: 212; csh: 117
file content (161 lines) | stat: -rw-r--r-- 6,265 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// RUN: %check_clang_tidy %s performance-implicit-conversion-in-loop %t

// ---------- Classes used in the tests ----------

// Iterator returning by value.
template <typename T>
struct Iterator {
  void operator++();
  T operator*();
  bool operator!=(const Iterator& other);
};

// Iterator returning by reference.
template <typename T>
struct RefIterator {
  void operator++();
  T& operator*();
  bool operator!=(const RefIterator& other);
};

// The template argument is an iterator type, and a view is an object you can
// run a for loop on.
template <typename T>
struct View {
  T begin();
  T end();
};

// With this class, the implicit conversion is a call to the (implicit)
// constructor of the class.
template <typename T>
class ImplicitWrapper {
 public:
  // Implicit!
  ImplicitWrapper(const T& t);
};

// With this class, the implicit conversion is a call to the conversion
// operators of SimpleClass and ComplexClass.
template <typename T>
class OperatorWrapper {
 public:
  explicit OperatorWrapper(const T& t);
};

struct SimpleClass {
  int foo;
  operator OperatorWrapper<SimpleClass>();
};

// The materialize expression is not the same when the class has a destructor,
// so we make sure we cover that case too.
class ComplexClass {
 public:
  ComplexClass();
  ~ComplexClass();
  operator OperatorWrapper<ComplexClass>();
};

typedef View<Iterator<SimpleClass>> SimpleView;
typedef View<RefIterator<SimpleClass>> SimpleRefView;
typedef View<Iterator<ComplexClass>> ComplexView;
typedef View<RefIterator<ComplexClass>> ComplexRefView;

// ---------- The test themselves ----------
// For each test we do, in the same order, const ref, non const ref, const
// value, non const value.

void SimpleClassIterator() {
  for (const SimpleClass& foo : SimpleView()) {}
  // This line does not compile because a temporary cannot be assigned to a non
  // const reference.
  // for (SimpleClass& foo : SimpleView()) {}
  for (const SimpleClass foo : SimpleView()) {}
  for (SimpleClass foo : SimpleView()) {}
}

void SimpleClassRefIterator() {
  for (const SimpleClass& foo : SimpleRefView()) {}
  for (SimpleClass& foo : SimpleRefView()) {}
  for (const SimpleClass foo : SimpleRefView()) {}
  for (SimpleClass foo : SimpleRefView()) {}
}

void ComplexClassIterator() {
  for (const ComplexClass& foo : ComplexView()) {}
  // for (ComplexClass& foo : ComplexView()) {}
  for (const ComplexClass foo : ComplexView()) {}
  for (ComplexClass foo : ComplexView()) {}
}

void ComplexClassRefIterator() {
  for (const ComplexClass& foo : ComplexRefView()) {}
  for (ComplexClass& foo : ComplexRefView()) {}
  for (const ComplexClass foo : ComplexRefView()) {}
  for (ComplexClass foo : ComplexRefView()) {}
}

void ImplicitSimpleClassIterator() {
  for (const ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the loop variable 'foo' is different from the one returned by the iterator and generates an implicit conversion; you can either change the type to the matching one ('const SimpleClass &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-conversion-in-loop]
  // for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
  for (const ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
  for (ImplicitWrapper<SimpleClass>foo : SimpleView()) {}
}

void ImplicitSimpleClassRefIterator() {
  for (const ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}
  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
  // for (ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}
  for (const ImplicitWrapper<SimpleClass> foo : SimpleRefView()) {}
  for (ImplicitWrapper<SimpleClass>foo : SimpleRefView()) {}
}

void ImplicitComplexClassIterator() {
  for (const ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}
  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
  // for (ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}
  for (const ImplicitWrapper<ComplexClass> foo : ComplexView()) {}
  for (ImplicitWrapper<ComplexClass>foo : ComplexView()) {}
}

void ImplicitComplexClassRefIterator() {
  for (const ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}
  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
  // for (ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}
  for (const ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}
  for (ImplicitWrapper<ComplexClass>foo : ComplexRefView()) {}
}

void OperatorSimpleClassIterator() {
  for (const OperatorWrapper<SimpleClass>& foo : SimpleView()) {}
  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
  // for (OperatorWrapper<SimpleClass>& foo : SimpleView()) {}
  for (const OperatorWrapper<SimpleClass> foo : SimpleView()) {}
  for (OperatorWrapper<SimpleClass>foo : SimpleView()) {}
}

void OperatorSimpleClassRefIterator() {
  for (const OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}
  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
  // for (OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}
  for (const OperatorWrapper<SimpleClass> foo : SimpleRefView()) {}
  for (OperatorWrapper<SimpleClass>foo : SimpleRefView()) {}
}

void OperatorComplexClassIterator() {
  for (const OperatorWrapper<ComplexClass>& foo : ComplexView()) {}
  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
  // for (OperatorWrapper<ComplexClass>& foo : ComplexView()) {}
  for (const OperatorWrapper<ComplexClass> foo : ComplexView()) {}
  for (OperatorWrapper<ComplexClass>foo : ComplexView()) {}
}

void OperatorComplexClassRefIterator() {
  for (const OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}
  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
  // for (OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}
  for (const OperatorWrapper<ComplexClass> foo : ComplexRefView()) {}
  for (OperatorWrapper<ComplexClass>foo : ComplexRefView()) {}
}