1 /* PR c++/80560 - warn on undefined memory operations involving non-trivial
4 { dg-options "-Wclass-memaccess -ftrack-macro-expansion=0" } */
6 typedef __SIZE_TYPE__ size_t;
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
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. */
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.
39 Trivial& operator= (U);
42 void test (Trivial *p, void *q, int x)
48 T (bzero, (p, sizeof *p));
51 T (bzero, (q, sizeof *p));
55 T (bcopy, (p, q, sizeof *p));
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));
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. */
112 int i; unsigned bf: 1; char *s; char a[4];
115 TrivialAccess () = default;
116 TrivialAccess (const TrivialAccess&) = default;
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)
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)
145 /* Verify that no warning is issued when the otherwise inaccessible
146 copy ctor and copy assignment can be accessed within the current
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)
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
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));
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[])
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." }
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));
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
258 HasTemplateDefault (U);
261 void test (HasTemplateDefault *p, const HasTemplateDefault &x,
262 const void *q, const unsigned char *s, const int 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));
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[])
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" }
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" }
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 {
384 HasPrivateCopy (const HasPrivateCopy&);
387 void test (HasPrivateCopy *p, const HasPrivateCopy &x,
388 const void *q, const unsigned char *s, const int 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" }
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[])
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" }
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
480 ~HasDeletedDtor () = delete;
483 void test (HasDeletedDtor *p, const HasDeletedDtor &x,
484 const void *q, const unsigned char *s, const int 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" }
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
529 void test (HasPrivateDtor *p, const HasPrivateDtor &x,
530 const void *q, const unsigned char *s, const int 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" }
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[])
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" }
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. */
613 #if __cplusplus > 199711L
614 void operator= (HasMoveAssign&&);
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&);
622 void test (HasMoveAssign *p, const HasMoveAssign &x,
623 const void *q, const unsigned char *s, const int 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" }
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&&);
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&);
680 void test (TrivialCopyHasMoveAssign *p, const TrivialCopyHasMoveAssign &x,
681 const void *q, const unsigned char *s, const int 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" }
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;
734 void test (TrivialMoveNontrivialCopyAssign *p,
735 const TrivialMoveNontrivialCopyAssign &x,
736 const void *q, const unsigned char *s, const int 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" }
773 #if !defined TEST || TEST == TEST_TRIVIAL_ASSIGN_REF_OVERLOAD
775 /* TrivialAssignRefOverload is a trivial type. */
776 struct TrivialAssignRefOverload {
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[])
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));
819 #if !defined TEST || TEST == TEST_TRIVIAL_ASSIGN_CSTREF_OVERLOAD
821 /* TrivialAssignCstOverload is a trivial type. */
822 struct TrivialAssignCstRefOverload {
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[])
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));
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[])
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" }
915 #if !defined TEST || TEST == TEST_HAS_VOLREF_ASSIGN
917 struct HasVolRefAssign {
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[])
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" }
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[])
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" }
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[])
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.
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 } } }
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[])
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.
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 } } }
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[])
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));
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[])
1191 const size_t n = *ia;
1193 // Zeroing out is not diagnosed because it's equivalent to value
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));
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[])
1252 const size_t n = *ia;
1254 // Zeroing out is not diagnosed because it's equivalent to value
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));
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[])
1313 const size_t n = *ia;
1315 // Zeroing out is not diagnosed because it's equivalent to value
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));
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[])
1374 const size_t n = *ia;
1376 // Zeroing out is not diagnosed because it's equivalent to value
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));
1423 #if !defined TEST || TEST == TEST_DEFAULT_CTOR_PRIVATE_ASSIGN
1425 /* Used to verify suggested alternatives. */
1426 struct HasDefaultPrivateAssign
1429 HasDefaultPrivateAssign ();
1431 void operator= (HasDefaultPrivateAssign&);
1434 void test (HasDefaultPrivateAssign *p, const HasDefaultPrivateAssign &x,
1435 const void *q, const unsigned char *s, const int 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" }
1494 #if !defined TEST || TEST == TEST_DEFAULT_CTOR_DELETED_ASSIGN
1496 /* Used to verify suggested alternatives. */
1497 struct HasDefaultDeletedAssign
1500 HasDefaultDeletedAssign ();
1502 void operator= (HasDefaultDeletedAssign&);
1505 void test (HasDefaultDeletedAssign *p, const HasDefaultDeletedAssign &x,
1506 const void *q, const unsigned char *s, const int 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" }
1565 #if !defined TEST || TEST == TEST_EXPRESSION
1567 void test_expr (int i)
1569 struct TestClass { TestClass () { } };
1574 T (bzero, (i < 0 ? &a : &b, 1)); // { dg-warning "bzero" }
1579 #if !defined TEST || TEST == TEST_CTOR
1584 #define T(fn, arglist) (fn arglist, sink (this))
1592 /* A ctor of a base class with no virtual function can do whatever
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));
1603 /* A dtor of a base class with no virtual function can do whatever
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));
1613 struct TestBaseVtable
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" }
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" }
1637 virtual void foo ();
1640 struct TestDerived: HasDefault
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));
1653 struct TestDerivedDtor: HasDefault
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" }
1671 // { dg-prune-output "defaulted and deleted functions" }