1 // { dg-do compile }
2 // { dg-options "-fopenmp" }
3 
SS4 struct S { int s; S () : s (0) {} S (int x) : s (x) {} ~S () {} };
TT5 struct T { int t; T () : t (0) {} T (int x) : t (x) {} ~T () {} };
6 
7 #pragma omp declare reduction (+: ::S: omp_out.s += omp_in.s)
8 #pragma omp declare reduction (*: S: omp_out.s *= omp_in.s) \
9 		    initializer (omp_priv (1))
10 #pragma omp declare reduction (foo: S: omp_out.s += omp_in.s)
11 
12 void
f1()13 f1 ()
14 {
15   S s, s2;
16   T t;
17   #pragma omp declare reduction (+: T: omp_out.t += omp_in.t)
18   #pragma omp parallel reduction (+: t) reduction (foo: s) reduction (*: s2)
19   s.s = 1, t.t = 1, s2.s = 2;
20   #pragma omp parallel reduction (::operator +: s)
21   s.s = 1;
22   #pragma omp parallel reduction (+: s)
23   s.s = 1;
24 }
25 
26 template <int N>
27 int
f2()28 f2 ()
29 {
30   S s, s2;
31   T t;
32   #pragma omp declare reduction (+: T: omp_out.t += omp_in.t)
33   #pragma omp parallel reduction (+: t) reduction (foo: s) reduction (*: s2)
34   s.s = 1, t.t = 1, s2.s = 2;
35   #pragma omp parallel reduction (::operator +: s)
36   s.s = 1;
37   #pragma omp parallel reduction (+: s)
38   s.s = 1;
39   return 0;
40 }
41 
42 int x = f2<0> ();
43 
44 void bar (S &);
45 
46 void
f3()47 f3 ()
48 {
49   #pragma omp declare reduction (foo: S: omp_out.s += omp_in.s) initializer (bar (omp_priv))
50   #pragma omp declare reduction (bar: S: omp_out.s += omp_in.s) initializer (bar (omp_orig)) // { dg-error "one of the initializer call arguments should be" }
51 }
52 
53 template <typename T>
54 int
f4()55 f4 ()
56 {
57   #pragma omp declare reduction (foo: T: omp_out.s += omp_in.s) initializer (bar (omp_priv))
58   #pragma omp declare reduction (bar: T: omp_out.s += omp_in.s) initializer (bar (omp_orig)) // { dg-error "one of the initializer call arguments should be" }
59   return 0;
60 }
61 
62 int y = f4 <S> ();
63 
64 namespace N1
65 {
66   #pragma omp declare reduction (+: ::S: omp_out.s *= omp_in.s)		// { dg-message "previous" }
67   #pragma omp declare reduction (+: S: omp_out.s += omp_in.s)		// { dg-error "redeclaration of" }
68   void
f5()69   f5 ()
70   {
71     #pragma omp declare reduction (f5: S: omp_out.s *= omp_in.s)	// { dg-message "previous" }
72     #pragma omp declare reduction (f5: ::S: omp_out.s += omp_in.s)	// { dg-error "redeclaration of" }
73   }
74 }
75 
76 namespace N2
77 {
78   struct U
79   {
80     #pragma omp declare reduction (bar: S: omp_out.s *= omp_in.s)	// { dg-message "previous" }
81     #pragma omp declare reduction (bar: S: omp_out.s += omp_in.s)	// { dg-error "cannot be overloaded" }
82   };
83 }
84 
85 namespace N3
86 {
87   #pragma omp declare reduction (+: ::S: omp_out.s *= omp_in.s)		// { dg-message "previous" }
88   #pragma omp declare reduction (+: T: omp_out.t += omp_in.t)
89   #pragma omp declare reduction (+: S: omp_out.s += omp_in.s)		// { dg-error "redeclaration of" }
90   #pragma omp declare reduction (n3: long: omp_out += omp_in)		// { dg-message "previous" }
91   #pragma omp declare reduction (n3: long int: omp_out += omp_in)	// { dg-error "redeclaration of" }
92   #pragma omp declare reduction (n3: short unsigned: omp_out += omp_in)
93   #pragma omp declare reduction (n3: short int: omp_out += omp_in)
94   void
f6()95   f6 ()
96   {
97     #pragma omp declare reduction (f6: T: omp_out.t += omp_in.t)
98     #pragma omp declare reduction (f6: S: omp_out.s *= omp_in.s)	// { dg-message "previous" }
99     #pragma omp declare reduction (f6: ::S: omp_out.s += omp_in.s)	// { dg-error "redeclaration of" }
100     #pragma omp declare reduction (f6: long: omp_out += omp_in)		// { dg-message "previous" }
101     #pragma omp declare reduction (f6: long int: omp_out += omp_in)	// { dg-error "redeclaration of" }
102     #pragma omp declare reduction (f6: short unsigned: omp_out += omp_in)
103     #pragma omp declare reduction (f6: short int: omp_out += omp_in)
104   }
105 }
106 
107 namespace N4
108 {
109   struct U
110   {
111     #pragma omp declare reduction (bar: T: omp_out.t += omp_in.t)
112     #pragma omp declare reduction (bar: S: omp_out.s *= omp_in.s)	// { dg-message "previous" }
113     #pragma omp declare reduction (bar: S: omp_out.s += omp_in.s)	// { dg-error "cannot be overloaded" }
114     #pragma omp declare reduction (bar: long: omp_out += omp_in)	// { dg-message "previous" }
115     #pragma omp declare reduction (bar: long int: omp_out += omp_in)	// { dg-error "cannot be overloaded" }
116     #pragma omp declare reduction (bar: short unsigned: omp_out += omp_in)
117     #pragma omp declare reduction (bar: short int: omp_out += omp_in)
118   };
119 }
120 
121 namespace N5
122 {
123   template <typename T>
124   int
f7()125   f7 ()
126   {
127     #pragma omp declare reduction (f7: T: omp_out.s *= omp_in.s)	// { dg-message "previous" }
128     #pragma omp declare reduction (f7: T: omp_out.s += omp_in.s)	// { dg-error "redeclaration of" }
129     return 0;
130   }
131   int x = f7 <S> ();
132   template <typename T>
133   struct U
134   {
135     #pragma omp declare reduction (bar: T: omp_out.s *= omp_in.s)	// { dg-message "previous" }
136     #pragma omp declare reduction (bar: T: omp_out.s += omp_in.s)	// { dg-error "cannot be overloaded" }
137   };
138   U<S> u;
139 }
140 
141 namespace N6
142 {
143   template <typename U>
144   int
f8()145   f8 ()
146   {
147     #pragma omp declare reduction (f8: T: omp_out.t += omp_in.t)
148     #pragma omp declare reduction (f8: U: omp_out.s *= omp_in.s)	// { dg-message "previous" }
149     #pragma omp declare reduction (f8: ::S: omp_out.s += omp_in.s)	// { dg-error "redeclaration of" }
150     #pragma omp declare reduction (f8: long: omp_out += omp_in)		// { dg-message "previous" }
151     #pragma omp declare reduction (f8: long int: omp_out += omp_in)	// { dg-error "redeclaration of" }
152     #pragma omp declare reduction (f8: short unsigned: omp_out += omp_in)
153     #pragma omp declare reduction (f8: short int: omp_out += omp_in)
154     return 0;
155   }
156   int x = f8 <S> ();
157   template <typename V>
158   struct U
159   {
160     typedef V V2;
161     #pragma omp declare reduction (bar: T: omp_out.t += omp_in.t)
162     #pragma omp declare reduction (bar: V: omp_out.s *= omp_in.s)	// { dg-message "previous" }
163     #pragma omp declare reduction (bar: V2: omp_out.s += omp_in.s)	// { dg-error "cannot be overloaded" }
164     #pragma omp declare reduction (bar: long: omp_out += omp_in)	// { dg-message "previous" }
165     #pragma omp declare reduction (bar: long int: omp_out += omp_in)	// { dg-error "cannot be overloaded" }
166     #pragma omp declare reduction (bar: short unsigned: omp_out += omp_in)
167     #pragma omp declare reduction (bar: short int: omp_out += omp_in)
168   };
169   U<S> u;
170 }
171 
172 namespace N7
173 {
174   #pragma omp declare reduction (+: S: omp_out.s += omp_in.s) initializer (omp_priv) // { dg-error "invalid initializer clause" }
175   #pragma omp declare reduction (+: T: omp_out.t += omp_in.t) initializer (omp_priv ()) // { dg-error "invalid initializer clause" }
176 }
177 
178 namespace N8
179 {
180   struct A { int a; A (); ~A (); };
181   struct B { int b; B (); ~B (); B (int); };
182   struct C : public A, B { int c; C (); ~C (); };
183   #pragma omp declare reduction (+:B:omp_out.b += omp_in.b) initializer (omp_priv (4))
184   void bar (C &);
baz()185   void baz ()
186   {
187     C a;
188     #pragma omp parallel reduction (+:a) // { dg-error "user defined reduction with constructor initializer for base class" }
189     bar (a);
190   }
191 }
192