1// { dg-do run }
2
3extern "C" void abort ();
4
5struct A { int a; A () : a (6) {} };
6struct B { int b; B () : b (5) {} };
7struct C { int c; C () : c (4) {} };
8struct D { int d; D () : d (3) {} };
9struct E : A, B {};
10struct F : C, D {};
11struct G : E, F {};
12void foo (B &);
13void foo (F &);
14#pragma omp declare reduction (+:B:omp_out.b += omp_in.b) \
15		    initializer(foo (omp_priv))
16
17void
18foo (B &x)
19{
20  if (x.b != 5)
21    abort ();
22  x.b = 9;
23}
24
25template <typename T>
26void bar (T &x, T &y, int z)
27{
28  if (z)
29    abort ();
30  x.a += y.a;
31}
32
33namespace N1
34{
35  struct A { int a; A () : a (0) {} };
36  #pragma omp declare reduction (+:A:bar (omp_out, omp_in, 0))
37};
38namespace N2
39{
40  struct B : N1::A { };
41  #pragma omp declare reduction (+:N1::A:bar (omp_out, omp_in, 1))
42};
43
44int
45main ()
46{
47  G g;
48  int i = 0;
49  #pragma omp parallel reduction(+:g, i)
50    {
51      if (g.a != 6 || g.b != 9 || g.c != 4 || g.d != 3)
52	abort ();
53      g.a = 1, g.b = 2, g.c = 3, g.d = 4, i = 1;
54    }
55  if (g.a != 6 || g.b != 5 + 2 * i || g.c != 4 || g.d != 3)
56    abort ();
57  N2::B b;
58  i = 0;
59  #pragma omp parallel reduction (+:b, i)
60    {
61      if (b.a != 0)
62	abort ();
63      b.a = 4;
64      i = 1;
65    }
66  if (b.a != 4 * i)
67    abort ();
68}
69