1/* This testcase is part of GDB, the GNU debugger.
2
3   Copyright 2019-2023 Free Software Foundation, Inc.
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18class ByVal {
19public:
20  ByVal (void);
21
22  int x;
23};
24
25ByVal::ByVal (void)
26{
27  x = 2;
28}
29
30class ByRef {
31public:
32  ByRef (void);
33
34  ByRef (const ByRef &rhs);
35
36  int x;
37};
38
39ByRef::ByRef (void)
40{
41  x = 2;
42}
43
44ByRef::ByRef (const ByRef &rhs)
45{
46  x = 3; /* ByRef-cctor */
47}
48
49class ArrayContainerByVal {
50public:
51  ByVal items[2];
52};
53
54int
55cbvArrayContainerByVal (ArrayContainerByVal arg)
56{
57  arg.items[0].x += 4;  // intentionally modify
58  return arg.items[0].x;
59}
60
61class ArrayContainerByRef {
62public:
63  ByRef items[2];
64};
65
66int
67cbvArrayContainerByRef (ArrayContainerByRef arg)
68{
69  arg.items[0].x += 4;  // intentionally modify
70  return arg.items[0].x;
71}
72
73class DynamicBase {
74public:
75  DynamicBase (void);
76
77  virtual int get (void);
78
79  int x;
80};
81
82DynamicBase::DynamicBase (void)
83{
84  x = 2;
85}
86
87int
88DynamicBase::get (void)
89{
90  return 42;
91}
92
93class Dynamic : public DynamicBase {
94public:
95  virtual int get (void);
96};
97
98int
99Dynamic::get (void)
100{
101  return 9999;
102}
103
104int
105cbvDynamic (DynamicBase arg)
106{
107  arg.x += 4;  // intentionally modify
108  return arg.x + arg.get ();
109}
110
111class Inlined {
112public:
113  Inlined (void);
114
115  __attribute__((always_inline))
116  Inlined (const Inlined &rhs)
117  {
118    x = 3;
119  }
120
121  int x;
122};
123
124Inlined::Inlined (void)
125{
126  x = 2;
127}
128
129int
130cbvInlined (Inlined arg)
131{
132  arg.x += 4;  // intentionally modify
133  return arg.x;
134}
135
136class DtorDel {
137public:
138  DtorDel (void);
139
140  ~DtorDel (void) = delete;
141
142  int x;
143};
144
145DtorDel::DtorDel (void)
146{
147  x = 2;
148}
149
150int
151cbvDtorDel (DtorDel arg)
152{
153  // Calling this method should be rejected
154  return arg.x;
155}
156
157class FourCCtor {
158public:
159  FourCCtor (void);
160
161  FourCCtor (FourCCtor &rhs);
162  FourCCtor (const FourCCtor &rhs);
163  FourCCtor (volatile FourCCtor &rhs);
164  FourCCtor (const volatile FourCCtor &rhs);
165
166  int x;
167};
168
169FourCCtor::FourCCtor (void)
170{
171  x = 2;
172}
173
174FourCCtor::FourCCtor (FourCCtor &rhs)
175{
176  x = 3;
177}
178
179FourCCtor::FourCCtor (const FourCCtor &rhs)
180{
181  x = 4;
182}
183
184FourCCtor::FourCCtor (volatile FourCCtor &rhs)
185{
186  x = 5;
187}
188
189FourCCtor::FourCCtor (const volatile FourCCtor &rhs)
190{
191  x = 6;
192}
193
194int
195cbvFourCCtor (FourCCtor arg)
196{
197  arg.x += 10;  // intentionally modify
198  return arg.x;
199}
200
201class TwoMCtor {
202public:
203  TwoMCtor (void);
204
205  /* Even though one move ctor is defaulted, the other
206     is explicit.  */
207  TwoMCtor (const TwoMCtor &&rhs);
208  TwoMCtor (TwoMCtor &&rhs) = default;
209
210  int x;
211};
212
213TwoMCtor::TwoMCtor (void)
214{
215  x = 2;
216}
217
218TwoMCtor::TwoMCtor (const TwoMCtor &&rhs)
219{
220  x = 3;
221}
222
223int
224cbvTwoMCtor (TwoMCtor arg)
225{
226  arg.x += 10;  // intentionally modify
227  return arg.x;
228}
229
230class TwoMCtorAndCCtor {
231public:
232  TwoMCtorAndCCtor (void);
233
234  TwoMCtorAndCCtor (const TwoMCtorAndCCtor &rhs) = default;
235
236  /* Even though one move ctor is defaulted, the other
237     is explicit.  This makes the type pass-by-ref.  */
238  TwoMCtorAndCCtor (const TwoMCtorAndCCtor &&rhs);
239  TwoMCtorAndCCtor (TwoMCtorAndCCtor &&rhs) = default;
240
241  int x;
242};
243
244TwoMCtorAndCCtor::TwoMCtorAndCCtor (void)
245{
246  x = 2;
247}
248
249TwoMCtorAndCCtor::TwoMCtorAndCCtor (const TwoMCtorAndCCtor &&rhs)
250{
251  x = 4;
252}
253
254int
255cbvTwoMCtorAndCCtor (TwoMCtorAndCCtor arg)
256{
257  arg.x += 10;  // intentionally modify
258  return arg.x;
259}
260
261ArrayContainerByVal arrayContainerByVal;
262ArrayContainerByRef arrayContainerByRef;
263Dynamic dynamic;
264Inlined inlined;
265// Cannot stack-allocate DtorDel
266DtorDel *dtorDel;
267FourCCtor fourCctor_c0v0;
268const FourCCtor fourCctor_c1v0;
269volatile FourCCtor fourCctor_c0v1;
270const volatile FourCCtor fourCctor_c1v1;
271TwoMCtor twoMctor;
272TwoMCtorAndCCtor twoMctorAndCctor;
273
274int
275main (void)
276{
277  int v;
278  dtorDel = new DtorDel;
279  /* Explicitly call the cbv function to make sure the compiler
280     will not omit any code in the binary.  */
281  v = cbvArrayContainerByVal (arrayContainerByVal);
282  v = cbvArrayContainerByRef (arrayContainerByRef);
283  v = cbvDynamic (dynamic);
284  v = cbvInlined (inlined);
285  v = cbvFourCCtor (fourCctor_c0v0);
286  v = cbvFourCCtor (fourCctor_c1v0);
287  v = cbvFourCCtor (fourCctor_c0v1);
288  v = cbvFourCCtor (fourCctor_c1v1);
289  /* v = cbvTwoMCtor (twoMctor); */ // This is illegal, cctor is deleted
290  v = cbvTwoMCtorAndCCtor (twoMctorAndCctor);
291
292  /* stop here */
293
294  return 0;
295}
296