1 // { dg-do run }
2
3 extern "C" void abort ();
4
5 namespace NS
6 {
7 struct U
8 {
9 void foo (U &, bool);
10 U ();
11 };
12 struct S
13 {
14 int s;
15 #pragma omp declare reduction (foo : U, S : omp_out.foo (omp_in, false))
16 #pragma omp declare reduction (foo : int : omp_out += omp_in) \
17 initializer (omp_priv = int ())
bazS18 void baz (int v)
19 {
20 S s;
21 int q = 0;
22 if (s.s != 6 || v != 0) abort ();
23 s.s = 20;
24 #pragma omp parallel num_threads (4) reduction (foo : s, v) \
25 reduction (::NS::U::operator + : q)
26 {
27 if (s.s != 6 || q != 0 || v != 0) abort ();
28 asm volatile ("" : "+m" (s.s), "+r" (q), "+r" (v));
29 s.s++; q++; v++;
30 }
31 if (s.s != 20 + q * 7 || q != v) abort ();
32 }
fooS33 void foo (S &x) { s += x.s; }
fooS34 void foo (S &x, bool y) { s += x.s; if (y) abort (); }
SS35 S (const S &x) { s = x.s + 1; }
SS36 S (const S &x, bool y) { s = x.s + 2; if (y) abort (); }
SS37 S () { s = 6; }
SS38 S (int x) { s = x; }
39 ~S ();
40 };
41 #pragma omp declare reduction (bar : S : omp_out.foo (omp_in)) \
42 initializer (omp_priv (8))
43 }
44
~S()45 NS::S::~S ()
46 {
47 if (s < 6) abort ();
48 s = -1;
49 /* Ensure the above store is not DSEd. */
50 asm volatile ("" : : "r" (&s) : "memory");
51 }
52
53 struct T : public NS::S
54 {
bazT55 void baz ()
56 {
57 S s;
58 int q = 0;
59 if (s.s != 6) abort ();
60 #pragma omp parallel num_threads (4) reduction (foo:s) \
61 reduction (+: q)
62 {
63 if (s.s != 6 || q != 0) abort ();
64 asm volatile ("" : "+m" (s.s), "+r" (q));
65 s.s += 2; q++;
66 }
67 if (s.s != 6 + q * 8) abort ();
68 }
69 };
70
71 int
main()72 main ()
73 {
74 NS::S s;
75 s.baz (0);
76 T t;
77 t.baz ();
78 int q = 0;
79 if (s.s != 6) abort ();
80 // Test ADL
81 #pragma omp parallel num_threads (4) reduction (bar:s) reduction (+:q)
82 {
83 if (s.s != 8 || q != 0) abort ();
84 asm volatile ("" : "+m" (s.s), "+r" (q));
85 s.s += 4; q++;
86 }
87 if (s.s != 6 + q * 12) abort ();
88 }
89