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