1 | // XFAIL: msvc |
2 | // Fails on windows due to issue #129023 |
3 | // RUN: %libomp-cxx20-compile-and-run | FileCheck %s --match-full-lines |
4 | |
5 | #ifndef HEADER |
6 | #define |
7 | |
8 | #include <cstdlib> |
9 | #include <cstdarg> |
10 | #include <cstdio> |
11 | #include <vector> |
12 | |
13 | struct Reporter { |
14 | const char *name; |
15 | |
16 | Reporter(const char *name) : name(name) { print(msg: "ctor" ); } |
17 | |
18 | Reporter() : name("<anon>" ) { print(msg: "ctor" ); } |
19 | |
20 | Reporter(const Reporter &that) : name(that.name) { print(msg: "copy ctor" ); } |
21 | |
22 | Reporter(Reporter &&that) : name(that.name) { print(msg: "move ctor" ); } |
23 | |
24 | ~Reporter() { print(msg: "dtor" ); } |
25 | |
26 | const Reporter &operator=(const Reporter &that) { |
27 | print(msg: "copy assign" ); |
28 | this->name = that.name; |
29 | return *this; |
30 | } |
31 | |
32 | const Reporter &operator=(Reporter &&that) { |
33 | print(msg: "move assign" ); |
34 | this->name = that.name; |
35 | return *this; |
36 | } |
37 | |
38 | struct Iterator { |
39 | const Reporter *owner; |
40 | int pos; |
41 | |
42 | Iterator(const Reporter *owner, int pos) : owner(owner), pos(pos) {} |
43 | |
44 | Iterator(const Iterator &that) : owner(that.owner), pos(that.pos) { |
45 | owner->print(msg: "iterator copy ctor" ); |
46 | } |
47 | |
48 | Iterator(Iterator &&that) : owner(that.owner), pos(that.pos) { |
49 | owner->print(msg: "iterator move ctor" ); |
50 | } |
51 | |
52 | ~Iterator() { owner->print(msg: "iterator dtor" ); } |
53 | |
54 | const Iterator &operator=(const Iterator &that) { |
55 | owner->print(msg: "iterator copy assign" ); |
56 | this->owner = that.owner; |
57 | this->pos = that.pos; |
58 | return *this; |
59 | } |
60 | |
61 | const Iterator &operator=(Iterator &&that) { |
62 | owner->print(msg: "iterator move assign" ); |
63 | this->owner = that.owner; |
64 | this->pos = that.pos; |
65 | return *this; |
66 | } |
67 | |
68 | bool operator==(const Iterator &that) const { |
69 | owner->print(msg: "iterator %d == %d" , 2 - this->pos, 2 - that.pos); |
70 | return this->pos == that.pos; |
71 | } |
72 | |
73 | bool operator!=(const Iterator &that) const { |
74 | owner->print(msg: "iterator %d != %d" , 2 - this->pos, 2 - that.pos); |
75 | return this->pos == that.pos; |
76 | } |
77 | |
78 | Iterator &operator++() { |
79 | owner->print(msg: "iterator prefix ++" ); |
80 | pos -= 1; |
81 | return *this; |
82 | } |
83 | |
84 | Iterator operator++(int) { |
85 | owner->print(msg: "iterator postfix ++" ); |
86 | auto result = *this; |
87 | pos -= 1; |
88 | return result; |
89 | } |
90 | |
91 | int operator*() const { |
92 | int result = 2 - pos; |
93 | owner->print(msg: "iterator deref: %i" , result); |
94 | return result; |
95 | } |
96 | |
97 | size_t operator-(const Iterator &that) const { |
98 | int result = (2 - this->pos) - (2 - that.pos); |
99 | owner->print(msg: "iterator distance: %d" , result); |
100 | return result; |
101 | } |
102 | |
103 | Iterator operator+(int steps) const { |
104 | owner->print(msg: "iterator advance: %i += %i" , 2 - this->pos, steps); |
105 | return Iterator(owner, pos - steps); |
106 | } |
107 | }; |
108 | |
109 | Iterator begin() const { |
110 | print(msg: "begin()" ); |
111 | return Iterator(this, 2); |
112 | } |
113 | |
114 | Iterator end() const { |
115 | print(msg: "end()" ); |
116 | return Iterator(this, -1); |
117 | } |
118 | |
119 | void print(const char *msg, ...) const { |
120 | va_list args; |
121 | va_start(args, msg); |
122 | printf(format: "[%s] " , name); |
123 | vprintf(format: msg, arg: args); |
124 | printf(format: "\n" ); |
125 | va_end(args); |
126 | } |
127 | }; |
128 | |
129 | int main() { |
130 | printf(format: "do\n" ); |
131 | Reporter A("A" ), B("B" ); |
132 | #pragma omp interchange |
133 | for (auto it = A.begin(); it != A.end(); ++it) |
134 | for (auto jt = B.begin(); jt != B.end(); ++jt) |
135 | printf(format: "i=%d j=%d\n" , *it, *jt); |
136 | printf(format: "done\n" ); |
137 | return EXIT_SUCCESS; |
138 | } |
139 | |
140 | #endif /* HEADER */ |
141 | |
142 | // CHECK: do |
143 | // CHECK-NEXT: [A] ctor |
144 | // CHECK-NEXT: [B] ctor |
145 | // CHECK-NEXT: [A] begin() |
146 | // CHECK-NEXT: [A] begin() |
147 | // CHECK-NEXT: [A] end() |
148 | // CHECK-NEXT: [A] iterator distance: 3 |
149 | // CHECK-NEXT: [B] begin() |
150 | // CHECK-NEXT: [B] begin() |
151 | // CHECK-NEXT: [B] end() |
152 | // CHECK-NEXT: [B] iterator distance: 3 |
153 | // CHECK-NEXT: [B] iterator advance: 0 += 0 |
154 | // CHECK-NEXT: [B] iterator move assign |
155 | // CHECK-NEXT: [A] iterator advance: 0 += 0 |
156 | // CHECK-NEXT: [A] iterator move assign |
157 | // CHECK-NEXT: [A] iterator deref: 0 |
158 | // CHECK-NEXT: [B] iterator deref: 0 |
159 | // CHECK-NEXT: i=0 j=0 |
160 | // CHECK-NEXT: [A] iterator dtor |
161 | // CHECK-NEXT: [A] iterator advance: 0 += 1 |
162 | // CHECK-NEXT: [A] iterator move assign |
163 | // CHECK-NEXT: [A] iterator deref: 1 |
164 | // CHECK-NEXT: [B] iterator deref: 0 |
165 | // CHECK-NEXT: i=1 j=0 |
166 | // CHECK-NEXT: [A] iterator dtor |
167 | // CHECK-NEXT: [A] iterator advance: 0 += 2 |
168 | // CHECK-NEXT: [A] iterator move assign |
169 | // CHECK-NEXT: [A] iterator deref: 2 |
170 | // CHECK-NEXT: [B] iterator deref: 0 |
171 | // CHECK-NEXT: i=2 j=0 |
172 | // CHECK-NEXT: [A] iterator dtor |
173 | // CHECK-NEXT: [B] iterator dtor |
174 | // CHECK-NEXT: [B] iterator advance: 0 += 1 |
175 | // CHECK-NEXT: [B] iterator move assign |
176 | // CHECK-NEXT: [A] iterator advance: 0 += 0 |
177 | // CHECK-NEXT: [A] iterator move assign |
178 | // CHECK-NEXT: [A] iterator deref: 0 |
179 | // CHECK-NEXT: [B] iterator deref: 1 |
180 | // CHECK-NEXT: i=0 j=1 |
181 | // CHECK-NEXT: [A] iterator dtor |
182 | // CHECK-NEXT: [A] iterator advance: 0 += 1 |
183 | // CHECK-NEXT: [A] iterator move assign |
184 | // CHECK-NEXT: [A] iterator deref: 1 |
185 | // CHECK-NEXT: [B] iterator deref: 1 |
186 | // CHECK-NEXT: i=1 j=1 |
187 | // CHECK-NEXT: [A] iterator dtor |
188 | // CHECK-NEXT: [A] iterator advance: 0 += 2 |
189 | // CHECK-NEXT: [A] iterator move assign |
190 | // CHECK-NEXT: [A] iterator deref: 2 |
191 | // CHECK-NEXT: [B] iterator deref: 1 |
192 | // CHECK-NEXT: i=2 j=1 |
193 | // CHECK-NEXT: [A] iterator dtor |
194 | // CHECK-NEXT: [B] iterator dtor |
195 | // CHECK-NEXT: [B] iterator advance: 0 += 2 |
196 | // CHECK-NEXT: [B] iterator move assign |
197 | // CHECK-NEXT: [A] iterator advance: 0 += 0 |
198 | // CHECK-NEXT: [A] iterator move assign |
199 | // CHECK-NEXT: [A] iterator deref: 0 |
200 | // CHECK-NEXT: [B] iterator deref: 2 |
201 | // CHECK-NEXT: i=0 j=2 |
202 | // CHECK-NEXT: [A] iterator dtor |
203 | // CHECK-NEXT: [A] iterator advance: 0 += 1 |
204 | // CHECK-NEXT: [A] iterator move assign |
205 | // CHECK-NEXT: [A] iterator deref: 1 |
206 | // CHECK-NEXT: [B] iterator deref: 2 |
207 | // CHECK-NEXT: i=1 j=2 |
208 | // CHECK-NEXT: [A] iterator dtor |
209 | // CHECK-NEXT: [A] iterator advance: 0 += 2 |
210 | // CHECK-NEXT: [A] iterator move assign |
211 | // CHECK-NEXT: [A] iterator deref: 2 |
212 | // CHECK-NEXT: [B] iterator deref: 2 |
213 | // CHECK-NEXT: i=2 j=2 |
214 | // CHECK-NEXT: [A] iterator dtor |
215 | // CHECK-NEXT: [B] iterator dtor |
216 | // CHECK-NEXT: [B] iterator dtor |
217 | // CHECK-NEXT: [B] iterator dtor |
218 | // CHECK-NEXT: [A] iterator dtor |
219 | // CHECK-NEXT: [A] iterator dtor |
220 | // CHECK-NEXT: done |
221 | // CHECK-NEXT: [B] iterator dtor |
222 | // CHECK-NEXT: [A] iterator dtor |
223 | // CHECK-NEXT: [B] dtor |
224 | // CHECK-NEXT: [A] dtor |
225 | |