|  | // { dg-do run } | 
|  |  | 
|  | #include <omp.h> | 
|  |  | 
|  | int c, d, e; | 
|  | struct R { R () {}; ~R () {}; int r; }; | 
|  | template <typename Q> | 
|  | struct T { T () : t(d) {}; virtual ~T () {}; Q t; }; | 
|  | template <typename Q> | 
|  | struct A : public R, virtual public T<Q> { A () : b(c), a(e) {} Q a; int &b; void m1 (); }; | 
|  |  | 
|  | void | 
|  | take (int &a, int &b, int &c, int &d) | 
|  | { | 
|  | asm volatile ("" : : "g" (&a), "g" (&b), "g" (&c), "g" (&d) : "memory"); | 
|  | } | 
|  |  | 
|  | template <typename Q> | 
|  | void | 
|  | A<Q>::m1 () | 
|  | { | 
|  | #pragma omp parallel private (a, T<Q>::t) shared (r, A::b) default(none) | 
|  | { | 
|  | int q = omp_get_thread_num (), q2; | 
|  | a = q; | 
|  | T<Q>::t = 3 * q; | 
|  | #pragma omp single copyprivate (q2) | 
|  | { | 
|  | r = 2 * q; | 
|  | b = 4 * q; | 
|  | q2 = q; | 
|  | } | 
|  | take (a, r, T<Q>::t, b); | 
|  | #pragma omp barrier | 
|  | if (A::a != q || R::r != 2 * q2 || T<Q>::t != 3 * q || A::b != 4 * q2) | 
|  | __builtin_abort (); | 
|  | } | 
|  | a = 7; | 
|  | r = 8; | 
|  | T<Q>::t = 9; | 
|  | b = 10; | 
|  | #pragma omp parallel shared (A::a) default (none) firstprivate (R::r, b) shared (T<Q>::t) | 
|  | { | 
|  | int q = omp_get_thread_num (), q2; | 
|  | take (A::a, R::r, T<Q>::t, A::b); | 
|  | if (a != 7 || r != 8 || T<Q>::t != 9 || b != 10) | 
|  | __builtin_abort (); | 
|  | R::r = 6 * q; | 
|  | #pragma omp barrier | 
|  | #pragma omp single copyprivate (q2) | 
|  | { | 
|  | A::a = 5 * q; | 
|  | T<Q>::t = 7 * q; | 
|  | q2 = q; | 
|  | } | 
|  | A::b = 8 * q; | 
|  | take (a, r, T<Q>::t, b); | 
|  | #pragma omp barrier | 
|  | if (a != 5 * q2 || r != 6 * q || T<Q>::t != 7 * q2 || b != 8 * q) | 
|  | __builtin_abort (); | 
|  | } | 
|  | a = 1; | 
|  | b = 2; | 
|  | R::r = 3; | 
|  | T<Q>::t = 4; | 
|  | bool f = false; | 
|  | #pragma omp parallel private (f) | 
|  | { | 
|  | f = false; | 
|  | #pragma omp single | 
|  | #pragma omp taskloop default(none) firstprivate (r, A::a, f) shared (T<Q>::t, b) | 
|  | for (int i = 0; i < 30; i++) | 
|  | { | 
|  | int q = omp_get_thread_num (); | 
|  | int tv, bv; | 
|  | #pragma omp atomic read | 
|  | tv = T<Q>::t; | 
|  | #pragma omp atomic read | 
|  | bv = A::b; | 
|  | if (i == 16) | 
|  | { | 
|  | if (bv != 2 || tv != 4) | 
|  | __builtin_abort (); | 
|  | } | 
|  | else | 
|  | { | 
|  | if ((bv != 2 && bv != 8) || (tv != 4 && tv != 9)) | 
|  | __builtin_abort (); | 
|  | } | 
|  | if (!f) | 
|  | { | 
|  | if (A::a != 1 || R::r != 3) | 
|  | __builtin_abort (); | 
|  | } | 
|  | else if (a != 7 * q || r != 9 * q) | 
|  | __builtin_abort (); | 
|  | take (a, r, T<Q>::t, b); | 
|  | A::a = 7 * q; | 
|  | R::r = 9 * q; | 
|  | if (i == 16) | 
|  | { | 
|  | #pragma omp atomic write | 
|  | A::b = 8; | 
|  | #pragma omp atomic write | 
|  | T<Q>::t = 9; | 
|  | } | 
|  | f = true; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | int | 
|  | main () | 
|  | { | 
|  | A<int> a; | 
|  | a.m1 (); | 
|  | A<int &> b; | 
|  | b.m1 (); | 
|  | } |