PR inline-asm/84742
[official-gcc.git] / gcc / testsuite / g++.dg / Wclass-memaccess.C
blob4783438888e23820dec213ca14dcf369175b4e2f
1 /* PR c++/80560 - warn on undefined memory operations involving non-trivial
2    types
3    { dg-do compile }
4    { dg-options "-Wclass-memaccess -ftrack-macro-expansion=0" } */
6 typedef __SIZE_TYPE__ size_t;
8 extern "C"
10 void* memcpy (void*, const void*, size_t);
11 void* memmove (void*, const void*, size_t);
12 void* mempcpy (void*, const void*, size_t);
13 void* memset (void*, int, size_t);
14 void* realloc (void*, size_t);
17 /* Ordinary bzcopy and bzero aren't recognized as special.  */
18 #define bcopy __builtin_bcopy
19 #define bzero __builtin_bzero
21 void sink (void*);
23 #define T(fn, arglist) ((fn arglist), sink (p))
25 #if !defined TEST || TEST == TEST_TRIVIAL
27 /* Trivial can be manipulated by raw memory functions.  */
28 struct Trivial
30   int i; unsigned bf: 1; char *s; char a[4];
32   // Non-copy assignment doesn't make the class non-trivial or not
33   // trivially assignable.
34   Trivial& operator= (int);
36   // Likewise, template assignment doesn't make the class non-trivial
37   // or not trivially assignable.
38   template <class U>
39   Trivial& operator= (U);
42 void test (Trivial *p, void *q, int x)
44   const size_t n = x;
46   T (bzero, (p, 1));
47   T (bzero, (p, n));
48   T (bzero, (p, sizeof *p));
49   T (bzero, (q, 1));
50   T (bzero, (q, n));
51   T (bzero, (q, sizeof *p));
53   T (bcopy, (p, q, 1));
54   T (bcopy, (p, q, n));
55   T (bcopy, (p, q, sizeof *p));
56   T (bcopy, (q, p, 1));
57   T (bcopy, (q, p, n));
58   T (bcopy, (q, p, sizeof *p));
60   T (memcpy, (p, q, 1));
61   T (memcpy, (p, q, n));
62   T (memcpy, (p, q, sizeof *p));
63   T (memcpy, (q, p, 1));
64   T (memcpy, (q, p, n));
65   T (memcpy, (q, p, sizeof *p));
67   T (memset, (p, 0, 1));
68   T (memset, (p, 0, n));
69   T (memset, (p, 0, sizeof *p));
70   T (memset, (q, 0, 1));
71   T (memset, (q, 0, n));
72   T (memset, (q, 0, sizeof *p));
74   T (memset, (p, 1, 1));
75   T (memset, (p, 1, n));
76   T (memset, (p, 1, sizeof *p));
77   T (memset, (q, 1, 1));
78   T (memset, (q, 1, n));
79   T (memset, (q, 1, sizeof *p));
81   T (memset, (p, x, 1));
82   T (memset, (p, x, n));
83   T (memset, (p, x, sizeof *p));
84   T (memset, (q, x, 1));
85   T (memset, (q, x, n));
86   T (memset, (q, x, sizeof *p));
88   T (memmove, (p, q, 1));
89   T (memmove, (p, q, n));
90   T (memmove, (p, q, sizeof *p));
91   T (memmove, (q, p, 1));
92   T (memmove, (q, p, n));
93   T (memmove, (q, p, sizeof *p));
95   T (q = realloc, (p, 1));
96   T (q = realloc, (p, n));
97   T (q = realloc, (p, sizeof *p));
99   T (q = realloc, (q, 1));
100   T (q = realloc, (q, n));
101   T (q = realloc, (q, sizeof *p));
104 #endif
106 #if !defined TEST || TEST == TEST_TRIVIAL_ACCESS
108 /* TrivialAccess can be manipulated by raw memory functions in contexts
109    that have access to the trivial specia functions.  */
110 struct TrivialAccess
112   int i; unsigned bf: 1; char *s; char a[4];
114 private:
115   TrivialAccess () = default;
116   TrivialAccess (const TrivialAccess&) = default;
117 protected:
118   TrivialAccess& operator= (const TrivialAccess&) = default;
120   void test_member (const TrivialAccess*, int);
122   friend void test_friend (TrivialAccess*, const TrivialAccess*, int);
125 void test (TrivialAccess *p, const TrivialAccess *q, int i)
127   void *pv;
128   (void)&pv;
130   /* Verify that a warning is issued when the copy ctor and copy
131      assignment are inaccessible.  */
132   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
133   T (bcopy, (q, p, sizeof *p));     // { dg-warning "bcopy" }
134   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
135   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
136   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
137   T (pv = realloc, (p, sizeof *p)); // { dg-warning "realloc" }
140 void test_friend (TrivialAccess *p, const TrivialAccess *q, int i)
142   void *pv;
143   (void)&pv;
145   /* Verify that no warning is issued when the otherwise inaccessible
146      copy ctor and copy assignment can be accessed within the current
147      context.  */
148   T (bzero, (p, sizeof *p));
149   T (bcopy, (q, p, sizeof *p));
150   T (memcpy, (p, q, sizeof *p));
151   T (memset, (p, i, sizeof *p));
152   T (memmove, (p, q, sizeof *p));
153   T (pv = realloc, (p, sizeof *p));
156 void TrivialAccess::test_member (const TrivialAccess *q, int i)
158   void *pv;
159   (void)&pv;
161   TrivialAccess *p = this;
163   /* Verify that no warning is issued when the otherwise inaccessible
164      copy ctor and copy assignment can be accessed within the current
165      context.  */
166   T (bzero, (p, sizeof *p));
167   T (bcopy, (q, p, sizeof *p));
168   T (memcpy, (p, q, sizeof *p));
169   T (memset, (p, i, sizeof *p));
170   T (memmove, (p, q, sizeof *p));
171   T (pv = realloc, (p, sizeof *p));
174 #endif
176 #if !defined TEST || TEST == TEST_HAS_DEFAULT
178 /* HasDefault is trivially copyable but should be initialized by
179    the ctor, not bzero or memset.  */
180 struct HasDefault { char a[4]; HasDefault (); };
182 void test (HasDefault *p, const HasDefault &x,
183            void *q, const unsigned char *s, const int ia[])
185   const int i = *ia;
186   const size_t n = *ia;
188   // HasDefault is neither trivial nor standard-layout.  The warning
189   // should mention the former since it's more permissive than the latter
190   // and so more informative.
191   T (bzero, (p, sizeof *p));        // { dg-warning "bzero(\[^\n\r\]*). clearing an object of non-trivial type .struct HasDefault.; use assignment or value-initialization instead" }
193   T (memset, (p, 0, sizeof *p));    // { dg-warning ".void\\* memset(\[^\n\r\]*). clearing an object of non-trivial type .struct HasDefault.; use assignment or value-initialization instead" }
195   T (memset, (p, 1, sizeof *p));    // { dg-warning ".void\\* memset(\[^\n\r\]*). writing to an object of non-trivial type .struct HasDefault.; use assignment instead" }
197   T (memset, (p, i, sizeof *p));    // { dg-warning ".void\\* memset(\[^\n\r\]*). writing to an object of non-trivial type .struct HasDefault.; use assignment instead" }
199   // Copying from another object of the same type is fine.
200   T (bcopy, (&x, p, sizeof *p));
201   T (bcopy, (&x, p, n));
203   T (memcpy, (p, &x, sizeof *p));
204   T (memcpy, (p, &x, n));
206   // Copying from a void* or character buffer is also fine.
207   T (bcopy, (q, p, sizeof *p));
208   T (bcopy, (q, p, n));
209   T (bcopy, (s, p, sizeof *p));
210   T (bcopy, (s, p, n));
212   T (memcpy, (p, q, sizeof *p));
213   T (memcpy, (p, q, n));
214   T (memcpy, (p, s, sizeof *p));
215   T (memcpy, (p, s, n));
217   T (memmove, (p, q, sizeof *p));
218   T (memmove, (p, q, n));
219   T (memmove, (p, s, sizeof *p));
220   T (memmove, (p, s, n));
222   T (mempcpy, (p, q, sizeof *p));
223   T (mempcpy, (p, q, n));
224   T (mempcpy, (p, s, sizeof *p));
225   T (mempcpy, (p, s, n));
227   // ...but partial copies are diagnosed.
228   T (memcpy, (p, &x, 1));   // { dg-warning "writing to an object of a non-trivial type .struct HasDefault. leaves 3 bytes unchanged" } */
229   T (memmove, (p, q, 2));   // { dg-warning "writing to an object of a non-trivial type .struct HasDefault. leaves 2 bytes unchanged" } */
230   T (mempcpy, (p, q, 3));   // { dg-warning "writing to an object of a non-trivial type .struct HasDefault. leaves 1 byte unchanged" } */
232   // Otherwise, copying from an object of an unrelated type is diagnosed.
233   T (memcpy, (p, ia, sizeof *p));  // { dg-warning ".void\\* memcpy(\[^\n\r\]*). copying an object of non-trivial type .struct HasDefault. from an array of .const int." }
234   extern long *ip;
235   T (memcpy, (p, ip, sizeof *p));  // { dg-warning ".void\\* memcpy(\[^\n\r\]*). copying an object of non-trivial type .struct HasDefault. from an array of .long." }
237   T (memmove, (p, ia, sizeof *p)); // { dg-warning ".void\\* memmove(\[^\n\r\]*). copying an object of non-trivial type .struct HasDefault. from an array of .const int." }
239   T (mempcpy, (p, ia, sizeof *p)); // { dg-warning ".void\\* mempcpy(\[^\n\r\]*). copying an object of non-trivial type .struct HasDefault. from an array of .const int." }
241   // Reallocating is the same as calling memcpy except that only
242   // shrinking reallocation is diagnosed.
243   T (q = realloc, (p, 1));   // { dg-warning "moving an object of non-trivial type .struct HasDefault. and size 4 into a region of size 1" }
244   T (q = realloc, (p, n));
245   T (q = realloc, (p, sizeof *p));
246   T (q = realloc, (p, sizeof *p + 1));
249 #endif
251 #if !defined TEST || TEST == TEST_HAS_TEMPLATE_DEFAULT
253 /* HasTemplateDefault should be initialized by means of the ctor,
254    not zeroed out by bzero/memset.  */
255 struct HasTemplateDefault
257   template <class U>
258   HasTemplateDefault (U);
261 void test (HasTemplateDefault *p, const HasTemplateDefault &x,
262            const void *q, const unsigned char *s, const int ia[])
264   const int i = *ia;
265   const size_t n = *ia;
267   // Zeroing out is diagnosed because value initialization is
268   // invalid (the template ctor makes default ctor unavailable).
269   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
270   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
271   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
272   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
274   // Copying from an object of any type is okay.
275   T (bcopy, (&x, p, sizeof *p));
276   T (bcopy, (q, p, sizeof *p));
277   T (bcopy, (s, p, sizeof *p));
278   T (bcopy, (ia, p, sizeof *p));    // { dg-warning "bcopy" }
280   T (memcpy, (p, &x, sizeof *p));
281   T (memcpy, (p, q, sizeof *p));
282   T (memcpy, (p, s, sizeof *p));
283   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
285   T (memmove, (p, &x, sizeof *p));
286   T (memmove, (p, q, sizeof *p));
287   T (memmove, (p, s, sizeof *p));
288   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
290   T (mempcpy, (p, &x, sizeof *p));
291   T (mempcpy, (p, q, sizeof *p));
292   T (mempcpy, (p, s, sizeof *p));
293   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
295   // Reallocating is the same as calling memcpy.
296   T (q = realloc, (p, 1));
297   T (q = realloc, (p, n));
298   T (q = realloc, (p, sizeof *p));
301 #endif
303 #if !defined TEST || TEST == TEST_HAS_COPY
305 /* HasCopy should be copied using the copy ctor or assignment, not
306    by memcpy or memmove.  Since it's non-trivial, it should not be zeroed
307    out by bzero/memset either and should instead use assignment and/or
308    value initialization.  */
309 struct HasCopy { int i; HasCopy (const HasCopy&); };
311 void test (HasCopy *p, const HasCopy &x,
312            const void *q, const unsigned char *s, const int ia[])
314   const int i = *ia;
315   const size_t n = *ia;
317   // Zeroing out is diagnosed because value initialization is invalid
318   // (the copy ctor makes no default ctor unavailable).  Since the type
319   // has no default ctor verify that the suggested alternative does not
320   // include value-initialization.
321   T (bzero, (p, sizeof *p));        // { dg-warning "clearing an object of non-trivial type .struct HasCopy.; use assignment instead" }
322   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
323   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
324   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
326   // Copying from an object of any type is diagnosed.
327   T (bcopy, (&x, p, sizeof *p));    // { dg-warning "bcopy" }
328   T (bcopy, (q, p, sizeof *p));     // { dg-warning "bcopy" }
329   T (bcopy, (s, p, sizeof *p));     // { dg-warning "bcopy" }
330   T (bcopy, (ia, p, sizeof *p));    // { dg-warning "bcopy" }
332   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "memcpy" }
333   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
334   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
335   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
337   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
338   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
339   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
340   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
342   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
343   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
344   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
345   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
347   // Reallocating is the same as calling memcpy.
348   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
349   T (q = realloc, (p, n));          // { dg-warning "realloc" }
350   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
353 #endif
355 #if !defined TEST || TEST == TEST_HAS_DEFAULT_AND_COPY
357 /* HasDefaultAndCopy is like HasCopy above but its default ctor takes
358    a default argument to verify that the suggested alternative offered
359    by the warning includes the default ctor (i.e., the test verifies
360    that the default ctor is recognized as such despite taking an argument.  */
362 struct HasDefaultAndCopy
364   HasDefaultAndCopy (int = 0);   // default ctor
365   HasDefaultAndCopy (const HasDefaultAndCopy&);
368 void test (HasDefaultAndCopy *p, const HasDefaultAndCopy &x)
370   T (bzero, (p, sizeof *p));        // { dg-warning "clearing an object of non-trivial type .struct HasDefaultAndCopy.; use assignment or value-initialization instead" }
371   T (memset, (p, 0, sizeof *p));    // { dg-warning "clearing an object of non-trivial type .struct HasDefaultAndCopy.; use assignment or value-initialization instead" }
374 #endif
376 #if !defined TEST || TEST == TEST_HAS_PRIVATE_COPY
378 /* HasPrivateCopy cannot be copied using memcpy or memmove.  Since it's
379    non-trivial, it it should not be zeroed out by bzero/memset either
380    and should instead use assignment and/or value initialization.  */
381 struct HasPrivateCopy {
382   int i;
383 private:
384   HasPrivateCopy (const HasPrivateCopy&);
387 void test (HasPrivateCopy *p, const HasPrivateCopy &x,
388            const void *q, const unsigned char *s, const int ia[])
390   const int i = *ia;
391   const size_t n = *ia;
393   // Zeroing out is diagnosed because value initialization is
394   // invalid (the copy ctor makes no default ctor unavailable).
395   // Verify also that the suggestion offers assignment but not
396   // value initialization (since the lattare is not available).
397   T (bzero, (p, sizeof *p));        // { dg-warning "clearing an object of non-trivial type .struct HasPrivateCopy.; use assignment instead" }
398   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
399   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
400   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
402   // Copying from an object of any type is diagnosed.
403   T (memcpy, (p, &x, sizeof *p));   // { dg-warning ".void\\* memcpy(\[^\n\r\]*). writing to an object of non-trivially copyable type .struct HasPrivateCopy.; use copy-assignment instead" }
404   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
405   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
406   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
408   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
409   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
410   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
411   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
413   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
414   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
415   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
416   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
418   // Reallocating is the same as calling memcpy.
419   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
420   T (q = realloc, (p, n));          // { dg-warning "realloc" }
421   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
424 #endif
426 #if !defined TEST || TEST == TEST_HAS_DTOR
428 /* HasDtor should be initialized using aggregate or memberwise intialization,
429    not bzero or memset.  */
430 struct HasDtor { int i; ~HasDtor (); };
432 void test (HasDtor *p, const HasDtor &x,
433            const void *q, const unsigned char *s, const int ia[])
435   const int i = *ia;
436   const size_t n = *ia;
438   // Zeroing out is diagnosed only because it's difficult not to.
439   // Otherwise, a class that's non-trivial only because it has
440   // a non-trivial dtor can be safely zeroed out (that's what
441   // value-initializing it does).
442   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
443   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
444   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
445   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
447   // Copying from an object of any type is diagnosed simply because
448   // a class with a user-defined dtor is not trivially copyable.
449   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "memcpy" }
450   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
451   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
452   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
454   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
455   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
456   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
457   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
459   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
460   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
461   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
462   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
464   // Reallocating is the same as calling memcpy.
465   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
466   T (q = realloc, (p, n));          // { dg-warning "realloc" }
467   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
470 #endif
472 #if !defined TEST || TEST == TEST_HAS_DELETED_DTOR
474 // HasDeletedDtor is trivial so clearing and cpying it is okay.
475 // Relocation would bypass the deleted dtor and so it's diagnosed.
477 struct HasDeletedDtor
479   int i;
480   ~HasDeletedDtor () = delete;
483 void test (HasDeletedDtor *p, const HasDeletedDtor &x,
484            const void *q, const unsigned char *s, const int ia[])
486   const int i = *ia;
487   const size_t n = *ia;
489   T (bzero, (p, sizeof *p));
490   T (memset, (p, 0, sizeof *p));
491   T (memset, (p, 1, sizeof *p));
492   T (memset, (p, i, sizeof *p));
494   T (memcpy, (p, &x, sizeof *p));
495   T (memcpy, (p, q, sizeof *p));
496   T (memcpy, (p, s, sizeof *p));
497   T (memcpy, (p, ia, sizeof *p));
499   T (memmove, (p, &x, sizeof *p));
500   T (memmove, (p, q, sizeof *p));
501   T (memmove, (p, s, sizeof *p));
502   T (memmove, (p, ia, sizeof *p));
504   T (mempcpy, (p, &x, sizeof *p));
505   T (mempcpy, (p, q, sizeof *p));
506   T (mempcpy, (p, s, sizeof *p));
507   T (mempcpy, (p, ia, sizeof *p));
509   // Reallocating is diagnosed.
510   T (q = realloc, (p, 1));          // { dg-warning "moving an object of type .struct HasDeletedDtor. with deleted destructor" }
511   T (q = realloc, (p, n));          // { dg-warning "realloc" }
512   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
515 #endif
517 #if !defined TEST || TEST == TEST_HAS_PRIVATE_DTOR
519 // Unlike HasDeletedDtor, HasPrivateDtor is okay to zero-out and copy
520 // but not relocate because doing so would bypass the deleted dtor..
522 struct HasPrivateDtor
524   int i;
525 private:
526   ~HasPrivateDtor ();
529 void test (HasPrivateDtor *p, const HasPrivateDtor &x,
530            const void *q, const unsigned char *s, const int ia[])
532   const int i = *ia;
533   const size_t n = *ia;
535   T (bzero, (p, sizeof *p));        // { dg-warning "clearing an object of non-trivial type .struct HasPrivateDtor.; use assignment or value-initialization instead" }
536   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
537   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
538   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
540   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "writing to an object of non-trivially copyable type .struct HasPrivateDtor.; use copy-assignment or copy-initialization instead" }
541   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
542   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
543   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
545   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
546   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
547   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
548   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
550   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
551   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
552   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
553   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
555   // Reallocating is diagnosed.
556   T (q = realloc, (p, 1));          // { dg-warning "moving an object of non-trivially copyable type .struct HasPrivateDtor." }
557   T (q = realloc, (p, n));          // { dg-warning "realloc" }
558   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
561 #endif
563 #if !defined TEST || TEST == TEST_HAS_COPY_ASSIGN
565 /* HasCopyAssign should be copied using the copy ctor or assignment, not
566    by memcpy or memmove.  */
567 struct HasCopyAssign { void operator= (HasCopyAssign&); };
569 void test (HasCopyAssign *p, const HasCopyAssign &x,
570            const void *q, const unsigned char *s, const int ia[])
572   const int i = *ia;
573   const size_t n = *ia;
575   // Zeroing out is diagnosed because it when used with an existing
576   // (already constructed) object in lieu of assigning a new value
577   // to it would bypass the user-defined assignment.
578   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
579   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
580   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
581   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
583   // Copying from an object of any type is diagnosed.
584   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "memcpy" }
585   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
586   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
587   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
589   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
590   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
591   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
592   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
594   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
595   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
596   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
597   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
599   // Reallocating is the same as calling memcpy.
600   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
601   T (q = realloc, (p, n));          // { dg-warning "realloc" }
602   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
605 #endif
607 #if !defined TEST || TEST == TEST_HAS_MOVE_ASSIGN
609 /* Like HasCopyAssign, HasMoveAssign should be copied using the copy
610    ctor or assignment, not by memcpy or memmove.  */
611 struct HasMoveAssign
613 #if __cplusplus > 199711L
614   void operator= (HasMoveAssign&&);
615 #else
616   // C++ 98 has no reference references.  Simply repeat the HasCopyAssign
617   // test to avoid having to add a conditional to every dg-warning directive.
618   void operator= (const HasMoveAssign&);
619 #endif
622 void test (HasMoveAssign *p, const HasMoveAssign &x,
623            const void *q, const unsigned char *s, const int ia[])
625   const int i = *ia;
626   const size_t n = *ia;
628   // Zeroing out is diagnosed because it when used with an existing
629   // (already constructed) object in lieu of assigning a new value
630   // to it would bypass the user-defined assignment.
631   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
632   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
633   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
634   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
636   // Copying from an object of any type is diagnosed.
637   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "memcpy" }
638   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
639   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
640   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
642   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
643   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
644   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
645   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
647   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
648   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
649   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
650   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
652   // Reallocating is the same as calling memcpy.
653   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
654   T (q = realloc, (p, n));          // { dg-warning "realloc" }
655   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
658 #endif
660 #if !defined TEST || TEST == TEST_TRIVIAL_COPY_HAS_MOVE_ASSIGN
662 /* TrivialCopyHasMoveAssign should be copied using the copy ctor
663    or assignment, not by memcpy or memmove.  */
664 struct TrivialCopyHasMoveAssign
666   typedef TrivialCopyHasMoveAssign Self;
668   Self& operator= (const Self&) = default;
670 #if __cplusplus > 199711L
671   Self& operator= (Self&&);
672 #else
673   // C++ 98 has no reference references.  Fake the test by adding
674   // a non-const overload of the assignment operator (which should
675   // have the same effect).
676   Self& operator= (Self&);
677 #endif
680 void test (TrivialCopyHasMoveAssign *p, const TrivialCopyHasMoveAssign &x,
681            const void *q, const unsigned char *s, const int ia[])
683   const int i = *ia;
684   const size_t n = *ia;
686   // Zeroing out is diagnosed because it when used with an existing
687   // (already constructed) object in lieu of assigning a new value
688   // to it would bypass the user-defined assignment.
689   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
690   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
691   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
692   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
694   // Copying from an object of any type is diagnosed.
695   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "memcpy" }
696   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
697   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
698   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
700   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
701   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
702   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
703   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
705   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
706   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
707   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
708   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
710   // Reallocating is the same as calling memcpy.
711   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
712   T (q = realloc, (p, n));          // { dg-warning "realloc" }
713   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
716 #endif
718 #if !defined TEST || TEST == TEST_TRIVIAL_MOVE_HAS_COPY_ASSIGN
720 /* TrivialMoveNontrivialCopyAssign should be copied using the copy ctor
721    or assignment, not by memcpy or memmove.  */
722 struct TrivialMoveNontrivialCopyAssign
724   typedef TrivialMoveNontrivialCopyAssign Self;
726   Self& operator= (const Self&);
727 #if __cplusplus > 199711L
728   // C++ 98 has no reference references.  Fake the test by simply
729   // not declaring the move assignment.
730   Self& operator= (Self&&) = default;
731 #endif
734 void test (TrivialMoveNontrivialCopyAssign *p,
735            const TrivialMoveNontrivialCopyAssign &x,
736            const void *q, const unsigned char *s, const int ia[])
738   const int i = *ia;
739   const size_t n = *ia;
741   // Zeroing out is diagnosed because it when used with an existing
742   // (already constructed) object in lieu of assigning a new value
743   // to it would bypass the user-defined assignment.
744   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
745   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
746   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
747   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
749   // Copying from an object of any type is diagnosed.
750   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "memcpy" }
751   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
752   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
753   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
755   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
756   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
757   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
758   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
760   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
761   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
762   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
763   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
765   // Reallocating is the same as calling memcpy.
766   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
767   T (q = realloc, (p, n));          // { dg-warning "realloc" }
768   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
771 #endif
773 #if !defined TEST || TEST == TEST_TRIVIAL_ASSIGN_REF_OVERLOAD
775 /* TrivialAssignRefOverload is a trivial type.  */
776 struct TrivialAssignRefOverload {
777   int i;
778   typedef TrivialAssignRefOverload Self;
780   Self& operator= (Self&) = default;
781   Self& operator= (const Self&) = delete;
782   Self& operator= (volatile Self&) = delete;
783   Self& operator= (const volatile Self&) = delete;
786 void test (TrivialAssignRefOverload *p, const TrivialAssignRefOverload &x,
787            const void *q, const unsigned char *s, const int ia[])
789   const int i = *ia;
790   const size_t n = *ia;
792   T (bzero, (p, sizeof *p));
793   T (memset, (p, 0, sizeof *p));
794   T (memset, (p, 1, sizeof *p));
795   T (memset, (p, i, sizeof *p));
797   T (memcpy, (p, &x, sizeof *p));
798   T (memcpy, (p, q, sizeof *p));
799   T (memcpy, (p, s, sizeof *p));
800   T (memcpy, (p, ia, sizeof *p));
802   T (memmove, (p, &x, sizeof *p));
803   T (memmove, (p, q, sizeof *p));
804   T (memmove, (p, s, sizeof *p));
805   T (memmove, (p, ia, sizeof *p));
807   T (mempcpy, (p, &x, sizeof *p));
808   T (mempcpy, (p, q, sizeof *p));
809   T (mempcpy, (p, s, sizeof *p));
810   T (mempcpy, (p, ia, sizeof *p));
812   T (q = realloc, (p, 1));
813   T (q = realloc, (p, n));
814   T (q = realloc, (p, sizeof *p));
817 #endif
819 #if !defined TEST || TEST == TEST_TRIVIAL_ASSIGN_CSTREF_OVERLOAD
821 /* TrivialAssignCstOverload is a trivial type.  */
822 struct TrivialAssignCstRefOverload {
823   int i;
824   typedef TrivialAssignCstRefOverload Self;
826   Self& operator= (Self&) = delete;
827   Self& operator= (const Self&) = default;
828   Self& operator= (volatile Self&) = delete;
829   Self& operator= (const volatile Self&) = delete;
832 void test (TrivialAssignCstRefOverload *p,
833            const TrivialAssignCstRefOverload &x,
834            const void *q, const unsigned char *s, const int ia[])
836   const int i = *ia;
837   const size_t n = *ia;
839   T (bzero, (p, sizeof *p));
840   T (memset, (p, 0, sizeof *p));
841   T (memset, (p, 1, sizeof *p));
842   T (memset, (p, i, sizeof *p));
844   T (memcpy, (p, &x, sizeof *p));
845   T (memcpy, (p, q, sizeof *p));
846   T (memcpy, (p, s, sizeof *p));
847   T (memcpy, (p, ia, sizeof *p));
849   T (memmove, (p, &x, sizeof *p));
850   T (memmove, (p, q, sizeof *p));
851   T (memmove, (p, s, sizeof *p));
852   T (memmove, (p, ia, sizeof *p));
854   T (mempcpy, (p, &x, sizeof *p));
855   T (mempcpy, (p, q, sizeof *p));
856   T (mempcpy, (p, s, sizeof *p));
857   T (mempcpy, (p, ia, sizeof *p));
859   T (q = realloc, (p, 1));
860   T (q = realloc, (p, n));
861   T (q = realloc, (p, sizeof *p));
864 #endif
866 #if !defined TEST || TEST == TEST_TRIVIAL_REF_HAS_VOLREF_ASSIGN
868 struct TrivialRefHasVolRefAssign
870   typedef TrivialRefHasVolRefAssign Self;
872   Self& operator= (Self&) = default;
873   Self& operator= (volatile Self&);
876 void test (TrivialRefHasVolRefAssign *p,
877            const TrivialRefHasVolRefAssign &x,
878            const void *q, const unsigned char *s, const int ia[])
880   const int i = *ia;
881   const size_t n = *ia;
883   // Zeroing out is diagnosed because it when used with an existing
884   // (already constructed) object in lieu of assigning a new value
885   // to it would bypass the user-defined assignment.
886   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
887   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
888   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
889   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
891   // Copying from an object of any type is diagnosed.
892   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "memcpy" }
893   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
894   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
895   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
897   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
898   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
899   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
900   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
902   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
903   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
904   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
905   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
907   // Reallocating is the same as calling memcpy.
908   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
909   T (q = realloc, (p, n));          // { dg-warning "realloc" }
910   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
913 #endif
915 #if !defined TEST || TEST == TEST_HAS_VOLREF_ASSIGN
917 struct HasVolRefAssign {
918   int i;
919   typedef HasVolRefAssign Self;
921   Self& operator= (volatile Self&);
924 void test (HasVolRefAssign *p, const HasVolRefAssign &x,
925            const void *q, const unsigned char *s, const int ia[])
927   const int i = *ia;
928   const size_t n = *ia;
930   // Zeroing out is diagnosed because it when used with an existing
931   // (already constructed) object in lieu of assigning a new value
932   // to it would bypass the user-defined assignment.
933   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
934   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
935   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
936   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
938   // Copying from an object of any type is diagnosed.
939   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "memcpy" }
940   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
941   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
942   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
944   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
945   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
946   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
947   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
949   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
950   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
951   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
952   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
954   // Reallocating is the same as calling memcpy.
955   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
956   T (q = realloc, (p, n));          // { dg-warning "realloc" }
957   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
960 #endif
962 #if !defined TEST || TEST == TEST_HAS_VIRTUALS
964 /* HasVirtuals should only be manipulated by the special member functions
965    and not by bzero, memcpy, or any other raw memory function. Doing
966    otherwse might corrupt the the vtable pointer.  */
967 struct HasVirtuals { int i; virtual void foo (); };
969 void test (HasVirtuals *p, const HasVirtuals &x,
970            const void *q, const unsigned char *s, const int ia[])
972   const int i = *ia;
973   const size_t n = *ia;
975   // Zeroing out is diagnosed because it corrupts the vtable.
976   T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
977   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
978   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
979   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
981   // Copying is diagnosed because when used to initialize an object
982   // could incorrectly initialize the vtable.
983   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "memcpy" }
984   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
985   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
986   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
988   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
989   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
990   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
991   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
993   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
994   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
995   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
996   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
998   // Reallocating is the same as calling memcpy.
999   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
1000   T (q = realloc, (p, n));          // { dg-warning "realloc" }
1001   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
1004 #endif
1006 #if !defined TEST || TEST == TEST_HAS_CONST_DATA
1008 /* HasConstData should only be initialized using aggregate initializatoon
1009    and not cleared by bzero, or copied into using memcpy.  Since it's not
1010    assignable allowing, raw memory functions to write into it would defeat
1011    const-correctness.  */
1012 struct HasConstData { const char a[4]; };
1014 void test (HasConstData *p, const HasConstData &x,
1015            const void *q, const unsigned char *s, const int ia[])
1017   const int i = *ia;
1018   const size_t n = *ia;
1020   // The following is ill-formed because HasConstData's cannot
1021   // be assigned (the assignment is implicitly deleted).  For
1022   // that reason all raw memory operations are diagnosed.
1023   // *p = x;
1025   // Zeroing out is diagnosed because if used with an existing
1026   // (already initialized) object could break const correctness.
1027   // Since the default ctor and copy assignment are both deleted,
1028   // verify that they're not suggested as a possible alternative.
1029   T (bzero, (p, sizeof *p));        // { dg-warning "clearing an object of type .struct HasConstData. with no trivial copy-assignment \\\[" "c++ 11 and later" { target { c++11 } } }
1030   // { dg-warning "clearing an object of type .struct HasConstData. with no trivial copy-assignment" "c++ 98" { target { c++98_only } } .-1 }
1031   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
1032   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
1033   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
1035   // Copying is also diagnosed.
1036   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "writing to an object of type .struct HasConstData. with no trivial copy-assignment; use copy-initialization instead" "c++ 11 and later" { target { c++11 } } }
1037   // { dg-warning "writing to an object of type .struct HasConstData. with no trivial copy-assignment" "c++ 98" { target { c++98_only } } .-1 }
1038   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
1039   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
1040   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
1042   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
1043   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
1044   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
1045   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
1047   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
1048   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
1049   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
1050   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
1052   // Reallocating is not diagnosed except in C++ 98 due to a bug.
1053   T (q = realloc, (p, 1));          // { dg-warning "moving an object of non-trivially copyable type .struct HasConstData.; use .new. and .delete. instead" "c++98" { target { c++98_only } } }
1054   T (q = realloc, (p, n));          // { dg-warning "realloc" "c++98" { target { c++98_only } } }
1055   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" "c++98" { target { c++98_only } } }
1058 #endif
1060 #if !defined TEST || TEST == TEST_HAS_REFERENCE
1062 /* HasReference should only be initialized using aggregate initializatoon
1063    and not cleared by bzero, or copied into using memcpy.  Since it's not
1064    assignable, allowing raw memory functions to write into it could
1065    corrupt the reference.  */
1066 struct HasReference { int &ci; };
1068 void test (HasReference *p, const HasReference &x,
1069            const void *q, const unsigned char *s, const int ia[])
1071   const int i = *ia;
1072   const size_t n = *ia;
1074   // Similarly to HasConstData, the following is ill-formed because
1075   // Hasreference cannot be assigned (the assignment is implicitly
1076   // deleted).  For that reason all raw memory operations are diagnosed.
1077   // *p = x;
1079   // Zeroing out is diagnosed because if used with an existing
1080   // (already initialized) object would invalidate the reference.
1081   // Since copy-assignment is deleted verify it's not suggested
1082   // as an alternative.  (C++ 11 and later only; C++ 98 is broken).
1083   T (bzero, (p, sizeof *p));        // { dg-warning "clearing an object of type .struct HasReference. with no trivial copy-assignment \\\[" "c++ 11 and later" { target { c++11 } } }
1084   // { dg-warning "clearing an object of type .struct HasReference. with no trivial copy-assignment" "c++ 98" { target { c++98_only } } .-1 }
1085   T (bzero, (p, n));                // { dg-warning "bzero" }
1086   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
1087   T (memset, (p, 0, n));            // { dg-warning "memset" }
1088   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
1089   T (memset, (p, 1, n));            // { dg-warning "memset" }
1090   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
1091   T (memset, (p, i, n));            // { dg-warning "memset" }
1093   // Copying is also diagnosed.
1094   T (memcpy, (p, &x, sizeof *p));   // { dg-warning "writing to an object of type .struct HasReference. with no trivial copy-assignment; use copy-initialization instead" "c++ 11 and later" { target { c++11 } } }
1095   // { dg-warning "writing to an object of type .struct HasReference. with no trivial copy-assignment" "c++ 98" { target { c++98_only } } .-1 }
1096   T (memcpy, (p, &x, n));           // { dg-warning "memcpy" }
1097   T (memcpy, (p, q, sizeof *p));    // { dg-warning "memcpy" }
1098   T (memcpy, (p, q, n));            // { dg-warning "memcpy" }
1099   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
1100   T (memcpy, (p, s, n));            // { dg-warning "memcpy" }
1101   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
1102   T (memcpy, (p, ia, n));           // { dg-warning "memcpy" }
1104   T (memmove, (p, &x, sizeof *p));  // { dg-warning "memmove" }
1105   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
1106   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
1107   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
1109   T (mempcpy, (p, &x, sizeof *p));  // { dg-warning "mempcpy" }
1110   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
1111   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
1112   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
1114   // Reallocating is not diagnosed because a type with a reference
1115   // is (perhaps surprisingly) trivially copyable.  It is diagnosed
1116   // in C++ 98 because of a bug, but it seems like it should be
1117   // diagnosed in all modes.
1118   T (q = realloc, (p, 1));          // { dg-warning "realloc" "c++ 98" { target { c++98_only } } }
1119   T (q = realloc, (p, n));          // { dg-warning "realloc" "c++ 98" { target { c++98_only } } }
1120   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" "c++ 98" { target { c++98_only } } }
1123 #endif
1125 #if !defined TEST || TEST == TEST_HAS_MEM_DATA_PTR
1127 /* HasMemDataPtr should only be initialized using aggregate initializatoon
1128    and not cleared by bzero or written into using memset because its
1129    representation is different from ordinary scalars (a null member data
1130    pointer is all ones).  It can be copied into using memcpy from an object
1131    of the same type or from a character buffer.  */
1132 struct HasMemDataPtr { int HasMemDataPtr::*p; };
1134 void test (HasMemDataPtr *p, const HasMemDataPtr &x,
1135            const void *q, const unsigned char *s, const int ia[])
1137   const int i = *ia;
1138   const size_t n = *ia;
1140   // Zeroing out is diagnosed because a null member data pointer has
1141   // a representation that's all bits set.
1142   T (bzero, (p, sizeof *p));        // { dg-warning "clearing an object of type .struct HasMemDataPtr. containing a pointer-to-member" }
1143   T (bzero, (p, n));                // { dg-warning "bzero" }
1144   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
1145   T (memset, (p, 0, n));            // { dg-warning "memset" }
1146   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
1147   T (memset, (p, 1, n));            // { dg-warning "memset" }
1148   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
1149   T (memset, (p, i, n));            // { dg-warning "memset" }
1151   // Copying is not diagnosed.
1152   T (memcpy, (p, &x, sizeof *p));
1153   T (memcpy, (p, &x, n));
1154   T (memcpy, (p, q, sizeof *p));
1155   T (memcpy, (p, q, n));
1156   T (memcpy, (p, s, sizeof *p));
1157   T (memcpy, (p, s, n));
1158   T (memcpy, (p, ia, sizeof *p));
1159   T (memcpy, (p, ia, n));
1161   T (memmove, (p, &x, sizeof *p));
1162   T (memmove, (p, q, sizeof *p));
1163   T (memmove, (p, s, sizeof *p));
1164   T (memmove, (p, ia, sizeof *p));
1166   T (mempcpy, (p, &x, sizeof *p));
1167   T (mempcpy, (p, q, sizeof *p));
1168   T (mempcpy, (p, s, sizeof *p));
1169   T (mempcpy, (p, ia, sizeof *p));
1171   // Reallocating is the same as calling memcpy.
1172   T (q = realloc, (p, 1));
1173   T (q = realloc, (p, n));
1174   T (q = realloc, (p, sizeof *p));
1175   T (q = realloc, (p, sizeof *p + 1));
1178 #endif
1180 #if !defined TEST || TEST == TEST_HAS_SOME_PRIVATE_DATA
1182 /* HasSomePrivateData can be initialized using value initialization
1183    and should not be written to using memset with a non-zero argument.
1184    Doing otherwise would break encapsulation.  */
1185 struct HasSomePrivateData { char a[2]; private: char b[2]; };
1187 void test (HasSomePrivateData *p, const HasSomePrivateData &x,
1188            const void *q, const unsigned char *s, const int ia[])
1190   const int i = *ia;
1191   const size_t n = *ia;
1193   // Zeroing out is not diagnosed because it's equivalent to value
1194   // initialization.
1195   T (bzero, (p, sizeof *p));
1196   T (memset, (p, 0, sizeof *p));
1197   // Calling memset with a (possibly) non-zero argument is diagnosed
1198   // because it breaks encapsulation.
1199   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
1200   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
1202   // Calling memcpy to copy from an object of the same type or from
1203   // a character or void buffer is not diagnosed because that's what
1204   // copy construction and copy assignment do.
1205   T (memcpy, (p, &x, sizeof *p));
1206   T (memcpy, (p, &x, n));
1207   T (memcpy, (p, q, sizeof *p));
1208   T (memcpy, (p, s, sizeof *p));
1209   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
1210   T (memcpy, (p, ia, n));           // { dg-warning "memcpy" }
1212   // Same as memcpy above.
1213   T (memmove, (p, &x, sizeof *p));
1214   T (memmove, (p, &x, n));
1215   T (memmove, (p, q, sizeof *p));
1216   T (memmove, (p, s, sizeof *p));
1217   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
1218   T (memmove, (p, ia, n));          // { dg-warning "memmove" }
1220   // Same as memcpy above.
1221   T (mempcpy, (p, &x, sizeof *p));
1222   T (mempcpy, (p, &x, n));
1223   T (mempcpy, (p, q, sizeof *p));
1224   T (mempcpy, (p, q, n));
1225   T (mempcpy, (p, s, sizeof *p));
1226   T (mempcpy, (p, s, n));
1227   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
1228   T (mempcpy, (p, ia, n));          // { dg-warning "mempcpy" }
1230   // Reallocating is the same as calling memcpy except that partial
1231   // copies are not diagnosed.
1232   T (q = realloc, (p, 1));
1233   T (q = realloc, (p, n));
1234   T (q = realloc, (p, sizeof *p));
1235   T (q = realloc, (p, sizeof *p + 1));
1238 #endif
1240 #if !defined TEST || TEST == TEST_HAS_SOME_PROTECTED_DATA
1242 /* Similarly to HasSomePrivateData, HasSomeProtectedData can be
1243    initialized using value initialization and should not be written
1244    to using memset with a non-zero argument.  Doing otherwise would
1245    break encapsulation.  */
1246 struct HasSomeProtectedData { char a[2]; protected: char b[2]; };
1248 void test (HasSomeProtectedData *p, const HasSomeProtectedData &x,
1249            const void *q, const unsigned char *s, const int ia[])
1251   const int i = *ia;
1252   const size_t n = *ia;
1254   // Zeroing out is not diagnosed because it's equivalent to value
1255   // initialization.
1256   T (bzero, (p, sizeof *p));
1257   T (memset, (p, 0, sizeof *p));
1258   // Calling memset with a (possibly) non-zero argument is diagnosed
1259   // because it breaks encapsulation.
1260   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
1261   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
1263   // Calling memcpy to copy from an object of the same type or from
1264   // a character or void buffer is not diagnosed because that's what
1265   // copy construction and copy assignment do.
1266   T (memcpy, (p, &x, sizeof *p));
1267   T (memcpy, (p, &x, n));
1268   T (memcpy, (p, q, sizeof *p));
1269   T (memcpy, (p, s, sizeof *p));
1270   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
1271   T (memcpy, (p, ia, n));           // { dg-warning "memcpy" }
1273   // Same as memcpy above.
1274   T (memmove, (p, &x, sizeof *p));
1275   T (memmove, (p, &x, n));
1276   T (memmove, (p, q, sizeof *p));
1277   T (memmove, (p, s, sizeof *p));
1278   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
1279   T (memmove, (p, ia, n));          // { dg-warning "memmove" }
1281   // Same as memcpy above.
1282   T (mempcpy, (p, &x, sizeof *p));
1283   T (mempcpy, (p, &x, n));
1284   T (mempcpy, (p, q, sizeof *p));
1285   T (mempcpy, (p, q, n));
1286   T (mempcpy, (p, s, sizeof *p));
1287   T (mempcpy, (p, s, n));
1288   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
1289   T (mempcpy, (p, ia, n));          // { dg-warning "mempcpy" }
1291   // Reallocating is the same as calling memcpy except that partial
1292   // copies are not diagnosed.
1293   T (q = realloc, (p, 1));
1294   T (q = realloc, (p, n));
1295   T (q = realloc, (p, sizeof *p));
1296   T (q = realloc, (p, sizeof *p + 1));
1299 #endif
1301 #if !defined TEST || TEST == TEST_HAS_ALL_PRIVATE_DATA
1303 /* Similarly to HasSomePrivateData, HasAllPrivateData should only be
1304    initialized using value initializatoon and should not be written
1305    to using memset with non-zero argument.  They are tested separately
1306    because unlike the former classes, these are standard layout.  */
1307 struct HasAllPrivateData { private: char a[4]; };
1309 void test (HasAllPrivateData *p, const HasAllPrivateData &x,
1310            const void *q, const unsigned char *s, const int ia[])
1312   const int i = *ia;
1313   const size_t n = *ia;
1315   // Zeroing out is not diagnosed because it's equivalent to value
1316   // initialization.
1317   T (bzero, (p, sizeof *p));
1318   T (memset, (p, 0, sizeof *p));
1319   // Calling memset with a (possibly) non-zero argument is diagnosed
1320   // because it breaks encapsulation.
1321   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
1322   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
1324   // Calling memcpy to copy from an object of the same type or from
1325   // a character or void buffer is not diagnosed because that's what
1326   // copy construction and copy assignment do.
1327   T (memcpy, (p, &x, sizeof *p));
1328   T (memcpy, (p, &x, n));
1329   T (memcpy, (p, q, sizeof *p));
1330   T (memcpy, (p, s, sizeof *p));
1331   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
1332   T (memcpy, (p, ia, n));           // { dg-warning "memcpy" }
1334   // Same as memcpy above.
1335   T (memmove, (p, &x, sizeof *p));
1336   T (memmove, (p, &x, n));
1337   T (memmove, (p, q, sizeof *p));
1338   T (memmove, (p, s, sizeof *p));
1339   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
1340   T (memmove, (p, ia, n));          // { dg-warning "memmove" }
1342   // Same as memcpy above.
1343   T (mempcpy, (p, &x, sizeof *p));
1344   T (mempcpy, (p, &x, n));
1345   T (mempcpy, (p, q, sizeof *p));
1346   T (mempcpy, (p, q, n));
1347   T (mempcpy, (p, s, sizeof *p));
1348   T (mempcpy, (p, s, n));
1349   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
1350   T (mempcpy, (p, ia, n));          // { dg-warning "mempcpy" }
1352   // Reallocating is the same as calling memcpy except that partial
1353   // copies are not diagnosed.
1354   T (q = realloc, (p, 1));
1355   T (q = realloc, (p, n));
1356   T (q = realloc, (p, sizeof *p));
1357   T (q = realloc, (p, sizeof *p + 1));
1360 #endif
1362 #if !defined TEST || TEST == TEST_HAS_ALL_PROTECTED_DATA
1364 /* Similarly to HasSomeProtectedData, HasAllProtectedData should only
1365    be initialized using value initializatoon and should not be written
1366    to using memset with non-zero argument.  They are tested separately
1367    because unlike the former classes, these are standard layout.  */
1368 struct HasAllProtectedData { protected: char a[4]; };
1370 void test (HasAllProtectedData *p, const HasAllProtectedData &x,
1371            const void *q, const unsigned char *s, const int ia[])
1373   const int i = *ia;
1374   const size_t n = *ia;
1376   // Zeroing out is not diagnosed because it's equivalent to value
1377   // initialization.
1378   T (bzero, (p, sizeof *p));
1379   T (memset, (p, 0, sizeof *p));
1380   // Calling memset with a (possibly) non-zero argument is diagnosed
1381   // because it breaks encapsulation.
1382   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
1383   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
1385   // Calling memcpy to copy from an object of the same type or from
1386   // a character or void buffer is not diagnosed because that's what
1387   // copy construction and copy assignment do.
1388   T (memcpy, (p, &x, sizeof *p));
1389   T (memcpy, (p, &x, n));
1390   T (memcpy, (p, q, sizeof *p));
1391   T (memcpy, (p, s, sizeof *p));
1392   T (memcpy, (p, ia, sizeof *p));   // { dg-warning "memcpy" }
1393   T (memcpy, (p, ia, n));           // { dg-warning "memcpy" }
1395   // Same as memcpy above.
1396   T (memmove, (p, &x, sizeof *p));
1397   T (memmove, (p, &x, n));
1398   T (memmove, (p, q, sizeof *p));
1399   T (memmove, (p, s, sizeof *p));
1400   T (memmove, (p, ia, sizeof *p));  // { dg-warning "memmove" }
1401   T (memmove, (p, ia, n));          // { dg-warning "memmove" }
1403   // Same as memcpy above.
1404   T (mempcpy, (p, &x, sizeof *p));
1405   T (mempcpy, (p, &x, n));
1406   T (mempcpy, (p, q, sizeof *p));
1407   T (mempcpy, (p, q, n));
1408   T (mempcpy, (p, s, sizeof *p));
1409   T (mempcpy, (p, s, n));
1410   T (mempcpy, (p, ia, sizeof *p));  // { dg-warning "mempcpy" }
1411   T (mempcpy, (p, ia, n));          // { dg-warning "mempcpy" }
1413   // Reallocating is the same as calling memcpy except that partial
1414   // copies are not diagnosed.
1415   T (q = realloc, (p, 1));
1416   T (q = realloc, (p, n));
1417   T (q = realloc, (p, sizeof *p));
1418   T (q = realloc, (p, sizeof *p + 1));
1421 #endif
1423 #if !defined TEST || TEST == TEST_DEFAULT_CTOR_PRIVATE_ASSIGN
1425 /* Used to verify suggested alternatives.  */
1426 struct HasDefaultPrivateAssign
1428   char a[4];
1429   HasDefaultPrivateAssign ();
1430 private:
1431   void operator= (HasDefaultPrivateAssign&);
1434 void test (HasDefaultPrivateAssign *p, const HasDefaultPrivateAssign &x,
1435            const void *q, const unsigned char *s, const int ia[])
1437   const int i = *ia;
1438   const size_t n = *ia;
1440   // HasDefaultPrivateAssign isn't trivial or assignable.  Verify
1441   // that the alternative suggested in the warning is to use copy or
1442   // default but not assignment.
1443   T (bzero, (p, sizeof *p));   // { dg-warning "bzero(\[^\n\r\]*). clearing an object of type .struct HasDefaultPrivateAssign. with no trivial copy-assignment; use value-initialization instead" "c++ 11 and later" { target { c++11 } } }
1444   // { dg-warning "bzero(\[^\n\r\]*). clearing an object of type .struct HasDefaultPrivateAssign. with no trivial copy-assignment; use value-initialization instead" "c++ 98" { target { c++98_only } } .-1 }
1446   T (memset, (p, 0, sizeof *p));   // { dg-warning ".void\\* memset(\[^\n\r\]*). clearing an object of type .struct HasDefaultPrivateAssign. with (deleted|no trivial) copy-assignment; use value-initialization instead" }
1448   T (memset, (p, 1, sizeof *p));   // { dg-warning ".void\\* memset(\[^\n\r\]*). writing to an object of type .struct HasDefaultPrivateAssign. with (deleted|no trivial) copy-assignment" }
1450   T (memset, (p, i, sizeof *p));   // { dg-warning ".void\\* memset(\[^\n\r\]*). writing to an object of type .struct HasDefaultPrivateAssign. with (deleted|no trivial) copy-assignment" }
1452   // Copying from another object of the same type is diagnosed because
1453   // the copy assignment is inaccessible.  Verify that the suggested
1454   // alternative is not copy assignment (C++ 98 is busted).
1455   T (memcpy, (p, &x, sizeof *p));   // { dg-warning ".void\\* memcpy(\[^\n\r\]*). writing to an object of type .struct HasDefaultPrivateAssign. with no trivial copy-assignment; use copy-initialization instead" "c++11 and later" { target c++11 } }
1456   // { dg-warning ".void\\* memcpy(\[^\n\r\]*). writing to an object of type .struct HasDefaultPrivateAssign. with no trivial copy-assignment" "c++98" { target c++98_only } .-1 }
1457   T (memcpy, (p, &x, n));           // { dg-warning "memcpy" }
1459   // Similarly for copying from a void* or character buffer.
1460   T (memcpy, (p, q, sizeof *p));    // { dg-warning ".void\\* memcpy(\[^\n\r\]*). writing to an object of type .struct HasDefaultPrivateAssign. with no trivial copy-assignment; use copy-initialization instead" "c++11 and later" { target c++11 } }
1461   // { dg-warning ".void\\* memcpy(\[^\n\r\]*). writing to an object of type .struct HasDefaultPrivateAssign. with no trivial copy-assignment" "c++98" { target c++98_only } ,-1 }
1462   T (memcpy, (p, q, n));            // { dg-warning "memcpy" }
1463   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
1464   T (memcpy, (p, s, n));            // { dg-warning "memcpy" }
1466   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
1467   T (memmove, (p, q, n));           // { dg-warning "memmove" }
1468   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
1469   T (memmove, (p, s, n));           // { dg-warning "memmove" }
1471   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
1472   T (mempcpy, (p, q, n));           // { dg-warning "mempcpy" }
1473   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
1474   T (mempcpy, (p, s, n));           // { dg-warning "mempcpy" }
1476   // Same for partial copies are diagnosed.
1477   T (memcpy, (p, &x, 1));   // { dg-warning "writing to an object of type .struct HasDefaultPrivateAssign. with (deleted|no trivial) copy-assignment" } */
1478   T (memmove, (p, q, 2));   // { dg-warning "memmove" } */
1479   T (mempcpy, (p, q, 3));   // { dg-warning "mempcpy" } */
1481   // Otherwise, copying from an object of an unrelated type is diagnosed.
1482   T (memcpy, (p, ia, sizeof *p));  // { dg-warning "writing to an object of type .struct HasDefaultPrivateAssign. with (deleted|no trivial) copy-assignment." }
1483   T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
1484   T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
1486   // Reallocating is the same as calling memcpy.
1487   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
1488   T (q = realloc, (p, n));          // { dg-warning "realloc" }
1489   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
1492 #endif
1494 #if !defined TEST || TEST == TEST_DEFAULT_CTOR_DELETED_ASSIGN
1496 /* Used to verify suggested alternatives.  */
1497 struct HasDefaultDeletedAssign
1499   char a[4];
1500   HasDefaultDeletedAssign ();
1501 private:
1502   void operator= (HasDefaultDeletedAssign&);
1505 void test (HasDefaultDeletedAssign *p, const HasDefaultDeletedAssign &x,
1506            const void *q, const unsigned char *s, const int ia[])
1508   const int i = *ia;
1509   const size_t n = *ia;
1511   // HasDefaultDeletedAssign isn't trivial or assignable.  Verify
1512   // that the alternative suggested in the warning is to use copy or
1513   // default but not assignment.
1514   T (bzero, (p, sizeof *p));   // { dg-warning "bzero(\[^\n\r\]*). clearing an object of type .struct HasDefaultDeletedAssign. with no trivial copy-assignment; use value-initialization instead" "c++ 11 and later" { target { c++11 } } }
1515   // { dg-warning "bzero(\[^\n\r\]*). clearing an object of type .struct HasDefaultDeletedAssign. with no trivial copy-assignment; use value-initialization instead" "c++ 98" { target { c++98_only } } .-1 }
1517   T (memset, (p, 0, sizeof *p));   // { dg-warning ".void\\* memset(\[^\n\r\]*). clearing an object of type .struct HasDefaultDeletedAssign. with (deleted|no trivial) copy-assignment; use value-initialization instead" }
1519   T (memset, (p, 1, sizeof *p));   // { dg-warning ".void\\* memset(\[^\n\r\]*). writing to an object of type .struct HasDefaultDeletedAssign. with (deleted|no trivial) copy-assignment" }
1521   T (memset, (p, i, sizeof *p));   // { dg-warning ".void\\* memset(\[^\n\r\]*). writing to an object of type .struct HasDefaultDeletedAssign. with (deleted|no trivial) copy-assignment" }
1523   // Copying from another object of the same type is diagnosed because
1524   // the copy assignment is inaccessible.  Verify that the suggested
1525   // alternative is not copy assignment (C++ 98 is busted).
1526   T (memcpy, (p, &x, sizeof *p));   // { dg-warning ".void\\* memcpy(\[^\n\r\]*). writing to an object of type .struct HasDefaultDeletedAssign. with no trivial copy-assignment; use copy-initialization instead" "c++11 and later" { target c++11 } }
1527   // { dg-warning ".void\\* memcpy(\[^\n\r\]*). writing to an object of type .struct HasDefaultDeletedAssign. with no trivial copy-assignment" "c++98" { target c++98_only } .-1 }
1528   T (memcpy, (p, &x, n));           // { dg-warning "memcpy" }
1530   // Similarly for copying from a void* or character buffer.
1531   T (memcpy, (p, q, sizeof *p));    // { dg-warning ".void\\* memcpy(\[^\n\r\]*). writing to an object of type .struct HasDefaultDeletedAssign. with no trivial copy-assignment; use copy-initialization instead" "c++11 and later" { target c++11 } }
1532   // { dg-warning ".void\\* memcpy(\[^\n\r\]*). writing to an object of type .struct HasDefaultDeletedAssign. with no trivial copy-assignment" "c++98" { target c++98_only } ,-1 }
1533   T (memcpy, (p, q, n));            // { dg-warning "memcpy" }
1534   T (memcpy, (p, s, sizeof *p));    // { dg-warning "memcpy" }
1535   T (memcpy, (p, s, n));            // { dg-warning "memcpy" }
1537   T (memmove, (p, q, sizeof *p));   // { dg-warning "memmove" }
1538   T (memmove, (p, q, n));           // { dg-warning "memmove" }
1539   T (memmove, (p, s, sizeof *p));   // { dg-warning "memmove" }
1540   T (memmove, (p, s, n));           // { dg-warning "memmove" }
1542   T (mempcpy, (p, q, sizeof *p));   // { dg-warning "mempcpy" }
1543   T (mempcpy, (p, q, n));           // { dg-warning "mempcpy" }
1544   T (mempcpy, (p, s, sizeof *p));   // { dg-warning "mempcpy" }
1545   T (mempcpy, (p, s, n));           // { dg-warning "mempcpy" }
1547   // Same for partial copies are diagnosed.
1548   T (memcpy, (p, &x, 1));   // { dg-warning "writing to an object of type .struct HasDefaultDeletedAssign. with (deleted|no trivial) copy-assignment" } */
1549   T (memmove, (p, q, 2));   // { dg-warning "memmove" } */
1550   T (mempcpy, (p, q, 3));   // { dg-warning "mempcpy" } */
1552   // Otherwise, copying from an object of an unrelated type is diagnosed.
1553   T (memcpy, (p, ia, sizeof *p));  // { dg-warning "writing to an object of type .struct HasDefaultDeletedAssign. with (deleted|no trivial) copy-assignment." }
1554   T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
1555   T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
1557   // Reallocating is the same as calling memcpy.
1558   T (q = realloc, (p, 1));          // { dg-warning "realloc" }
1559   T (q = realloc, (p, n));          // { dg-warning "realloc" }
1560   T (q = realloc, (p, sizeof *p));  // { dg-warning "realloc" }
1563 #endif
1565 #if !defined TEST || TEST == TEST_EXPRESSION
1567 void test_expr (int i)
1569   struct TestClass { TestClass () { } };
1570   TestClass a, b;
1572   static void *p;
1574   T (bzero, (i < 0 ? &a : &b, 1));  // { dg-warning "bzero" }
1577 #endif
1579 #if !defined TEST || TEST == TEST_CTOR
1581 void test_ctor ()
1583 #undef T
1584 #define T(fn, arglist) (fn arglist, sink (this))
1586   static void *p;
1588   struct TestBase
1589   {
1590     TestBase ()
1591     {
1592       /* A ctor of a base class with no virtual function can do whatever
1593          it wants.  */
1594       T (bzero, (this, sizeof *this));
1595       T (memset, (this, 0, sizeof *this));
1596       T (memcpy, (this, p, sizeof *this));
1597       T (memmove, (this, p, sizeof *this));
1598       T (mempcpy, (this, p, sizeof *this));
1599     }
1601     ~TestBase ()
1602     {
1603       /* A dtor of a base class with no virtual function can do whatever
1604          it wants.  */
1605       T (bzero, (this, sizeof *this));
1606       T (memset, (this, 0, sizeof *this));
1607       T (memcpy, (this, p, sizeof *this));
1608       T (memmove, (this, p, sizeof *this));
1609       T (mempcpy, (this, p, sizeof *this));
1610     }
1611   };
1613   struct TestBaseVtable
1614   {
1615     TestBaseVtable ()
1616     {
1617       /* A ctor of a base class with virtual function is treated
1618          as an ordinary function.  */
1619       T (bzero, (this, sizeof *this));      // { dg-warning "bzero" }
1620       T (memset, (this, 0, sizeof *this));  // { dg-warning "memset" }
1621       T (memcpy, (this, p, sizeof *this));  // { dg-warning "memcpy" }
1622       T (memmove, (this, p, sizeof *this)); // { dg-warning "memmove" }
1623       T (mempcpy, (this, p, sizeof *this)); // { dg-warning "mempcpy" }
1624     }
1626     ~TestBaseVtable ()
1627     {
1628       /* A dtor of a base class with virtual function is treated
1629          as an ordinary function.  */
1630       T (bzero, (this, sizeof *this));      // { dg-warning "bzero" }
1631       T (memset, (this, 0, sizeof *this));  // { dg-warning "memset" }
1632       T (memcpy, (this, p, sizeof *this));  // { dg-warning "memcpy" }
1633       T (memmove, (this, p, sizeof *this)); // { dg-warning "memmove" }
1634       T (mempcpy, (this, p, sizeof *this)); // { dg-warning "mempcpy" }
1635     }
1637     virtual void foo ();
1638   };
1640   struct TestDerived: HasDefault
1641   {
1642     TestDerived ()
1643     {
1644       /* A derived class ctor is treated as an ordinary function.  */
1645       T (bzero, (this, sizeof *this));      // { dg-warning "bzero" }
1646       T (memset, (this, 0, sizeof *this));  // { dg-warning "memset" }
1647       T (memcpy, (this, p, sizeof *this));
1648       T (memmove, (this, p, sizeof *this));
1649       T (mempcpy, (this, p, sizeof *this));
1650     }
1651   };
1653   struct TestDerivedDtor: HasDefault
1654   {
1655     ~TestDerivedDtor ()
1656     {
1657       /* A derived class dtor is treated as an ordinary function though
1658          it probably shouldn't be unless the base dtor is trivial.  But
1659          it doesn't seem worth the trouble.  */
1660       T (bzero, (this, sizeof *this));      // { dg-warning "bzero" }
1661       T (memset, (this, 0, sizeof *this));  // { dg-warning "memset" }
1662       T (memcpy, (this, p, sizeof *this));  // { dg-warning "memcpy" }
1663       T (memmove, (this, p, sizeof *this)); // { dg-warning "memmove" }
1664       T (mempcpy, (this, p, sizeof *this)); // { dg-warning "mempcpy" }
1665     }
1666   };
1669 #endif
1671 // { dg-prune-output "defaulted and deleted functions" }