1// { dg-do run } 2 3extern "C" void abort (); 4 5void 6dblinit (double *p) 7{ 8 *p = 2.0; 9} 10 11namespace NS 12{ 13 template <int N> 14 struct U 15 { 16 void foo (U &, bool); 17 U (); 18 }; 19 template <int N> 20 struct S 21 { 22 int s; 23 #pragma omp declare reduction (foo : U<0>, S : omp_out.foo (omp_in, false)) 24 #pragma omp declare reduction (foo : int : omp_out += omp_in) \ 25 initializer (omp_priv = N + 2) 26 #pragma omp declare reduction (foo : double : omp_out += omp_in) \ 27 initializer (dblinit (&omp_priv)) 28 void baz (int v) 29 { 30 S s; 31 int q = 0; 32 if (s.s != 6 || v != 0) abort (); 33 s.s = 20; 34 double d = 4.0; 35 #pragma omp parallel num_threads (4) reduction (foo : s, v, d) \ 36 reduction (::NS::U<N>::operator + : q) 37 { 38 if (s.s != 6 || q != 0 || v != N + 2 || d != 2.0) abort (); 39 asm volatile ("" : "+m" (s.s), "+r" (q), "+r" (v)); 40 s.s++; q++; v++; 41 } 42 if (s.s != 20 + q * 7 || (N + 3) * q != v || d != 4.0 + 2.0 * q) 43 abort (); 44 } 45 void foo (S &x) { s += x.s; } 46 void foo (S &x, bool y) { s += x.s; if (y) abort (); } 47 S (const S &x) { s = x.s + 1; } 48 S (const S &x, bool y) { s = x.s + 2; if (y) abort (); } 49 S () { s = 6; } 50 S (int x) { s = x; } 51 ~S (); 52 }; 53 #pragma omp declare reduction (bar : S<1> : omp_out.foo (omp_in)) \ 54 initializer (omp_priv (8)) 55} 56 57template <int N> 58NS::S<N>::~S () 59{ 60 if (s < 6) abort (); 61 s = -1; 62 /* Ensure the above store is not DSEd. */ 63 asm volatile ("" : : "r" (&s) : "memory"); 64} 65 66template <int N> 67struct T : public NS::S<N> 68{ 69 void baz () 70 { 71 NS::S<N> s; 72 int q = 0; 73 if (s.s != 6) abort (); 74 #pragma omp parallel num_threads (4) reduction (foo:s) \ 75 reduction (+: q) 76 { 77 if (s.s != 6 || q != 0) abort (); 78 asm volatile ("" : "+m" (s.s), "+r" (q)); 79 s.s += 2; q++; 80 } 81 if (s.s != 6 + q * 8) abort (); 82 } 83}; 84 85struct W 86{ 87 int v; 88 W () : v (6) {} 89 ~W () {} 90}; 91 92template <typename T, typename D> 93struct V 94{ 95 #pragma omp declare reduction (baz: T: omp_out.s += omp_in.s) \ 96 initializer (omp_priv (11)) 97 #pragma omp declare reduction (baz: D: omp_out += omp_in) \ 98 initializer (dblinit (&omp_priv)) 99 static void dblinit (D *x) { *x = 3.0; } 100 void baz () 101 { 102 T t; 103 V v; 104 int q = 0; 105 D d = 4.0; 106 if (t.s != 6 || v.v != 4) abort (); 107 #pragma omp declare reduction (+ : V, W : omp_out.v -= omp_in.v) \ 108 initializer (omp_priv (12)) 109 { 110 #pragma omp declare reduction (+ : W, V : omp_out.v += omp_in.v) \ 111 initializer (omp_priv (9)) 112 #pragma omp parallel num_threads (4) reduction (+: v, q) \ 113 reduction (baz: t, d) 114 { 115 if (t.s != 11 || v.v != 9 || q != 0 || d != 3.0) abort (); 116 asm volatile ("" : "+m" (t.s), "+m" (v.v), "+r" (q)); 117 t.s += 2; v.v += 3; q++; 118 } 119 if (t.s != 6 + 13 * q || v.v != 4 + 12 * q || d != 4.0 + 3.0 * q) 120 abort (); 121 } 122 } 123 int v; 124 V () : v (4) {} 125 V (int x) : v (x) {} 126 ~V () {} 127}; 128 129int 130main () 131{ 132 NS::S<0> u; 133 u.baz (0); 134 T<2> t; 135 t.baz (); 136 NS::S<1> s; 137 int q = 0; 138 if (s.s != 6) abort (); 139 // Test ADL 140 #pragma omp parallel num_threads (4) reduction (bar:s) reduction (+:q) 141 { 142 if (s.s != 8 || q != 0) abort (); 143 asm volatile ("" : "+m" (s.s), "+r" (q)); 144 s.s += 4; q++; 145 } 146 if (s.s != 6 + q * 12) abort (); 147 V <NS::S <0>, double> v; 148 v.baz (); 149} 150