| /* { dg-do compile } */ |
| /* { dg-options "-Wplacement-new -fpermissive" } */ |
| |
| typedef __typeof__ (sizeof 0) size_t; |
| |
| typedef int int32_t __attribute__((mode (__SI__))); |
| |
| void* operator new (size_t, void *p) { return p; } |
| void* operator new[] (size_t, void *p) { return p; } |
| |
| static __attribute__ ((used))char c; |
| static __attribute__ ((used))char ac1 [1]; |
| static __attribute__ ((used))char ac2 [2]; |
| static __attribute__ ((used))char ac3 [3]; |
| static __attribute__ ((used))char ac4 [4]; |
| static __attribute__ ((used))char ac5 [5]; |
| static __attribute__ ((used))char ac6 [6]; |
| static __attribute__ ((used))char ac7 [7]; |
| static __attribute__ ((used))char ac8 [8]; |
| |
| static __attribute__ ((used))char ac1_1 [1][1]; |
| static __attribute__ ((used))char ac1_2 [1][2]; |
| static __attribute__ ((used))char ac2_1 [2][1]; |
| static __attribute__ ((used))char ac2_2 [2][2]; |
| |
| static __attribute__ ((used))short s; |
| static __attribute__ ((used))short as1 [1]; |
| static __attribute__ ((used))short as2 [2]; |
| |
| static __attribute__ ((used))struct SC { char c; char *pc; void *pv; } sc; |
| static __attribute__ ((used))struct SAC1 { char ac [1]; } sac1; |
| static __attribute__ ((used))struct SAC2 { char ac [2]; } sac2; |
| static __attribute__ ((used))struct SAC3 { char ac [3]; } sac3; |
| static __attribute__ ((used))struct SAC4 { char ac [4]; } sac4; |
| |
| static __attribute__ ((used))struct SSC { SC sc; int32_t x; } ssc; |
| static __attribute__ ((used))struct SSAC1 { SAC1 sac; } ssac1; |
| static __attribute__ ((used))struct SSAC2 { SAC2 sac; } ssac2; |
| static __attribute__ ((used))struct SSAC3 { SAC3 sac; } ssac3; |
| static __attribute__ ((used))struct SSAC4 { SAC4 sac; } ssac4; |
| |
| static __attribute__ ((used))struct SSAC4_2 { SSAC4 ssac4_2 [2]; } sssac4_2; |
| |
| static __attribute__ ((used))union UAC1 { char c; char ac [1]; } uac1; |
| static __attribute__ ((used))union UAC2 { char c; char ac [2]; } uac2; |
| static __attribute__ ((used))union UAC3 { char c; char ac [3]; } uac3; |
| static __attribute__ ((used))union UAC4 { char c; char ac [4]; } uac4; |
| |
| static __attribute__ ((used))SC fsc () { return SC (); } |
| static __attribute__ ((used))SAC1 fasc1 () { return SAC1 (); } |
| static __attribute__ ((used))SAC2 fasc2 () { return SAC2 (); } |
| static __attribute__ ((used))SAC3 fasc3 () { return SAC3 (); } |
| static __attribute__ ((used))SAC4 fasc4 () { return SAC4 (); } |
| |
| static __attribute__ ((used))void *r; |
| |
| static __attribute__ ((used))void* ptr () { return 0; } |
| |
| static __attribute__ ((used)) |
| void test (void *p, int32_t n) |
| { |
| { |
| void *q = p; |
| struct { void *p; } s = { p }; |
| |
| // Verify that none of function arguments, local or global |
| // variables, or function return values trigger the warning. |
| new (p) char; |
| new (q) char; |
| new (r) char; |
| new (s.p) char; |
| new (ptr ()) char; |
| |
| new (p) char [32]; |
| new (q) char [32]; |
| new (r) char [32]; |
| new (s.p) char [32]; |
| new (ptr ()) char [32]; |
| |
| new (&p) char; |
| new (&q) char; |
| new (&r) char; |
| |
| // Using address of objects, however, must trigger the warning. |
| new (&p) char [32]; // { dg-warning "placement" } |
| new (&q) char [32]; // { dg-warning "placement" } |
| new (&r) char [32]; // { dg-warning "placement" } |
| } |
| |
| enum { N0, N1, N2, N3 }; |
| |
| new (&c) char; |
| |
| // Warn for the common case when constructing at an offset from |
| // the beginning of an array that doesn't leave enough space for |
| // the object. |
| new (&c + 0) char; // okay |
| new (&c + n) char; // okay (n is unknown) |
| new (&c + 1) char; // { dg-warning "placement" } |
| new (&c + N0) char; |
| new (&c + N1) char; // { dg-warning "placement" } |
| |
| // No warning is issued when constructing an array in space exactly |
| // its size even though strictly speaking a compiler is allowed to |
| // add a cookie to the array (gcc does not). |
| new (&c) char [1]; |
| new (&c) char [sizeof c]; |
| new (&c) char [n]; |
| new (&c) char [1][1]; |
| new (&c) char [1][1][1]; |
| new (&c + N1) char [1][1][1]; // { dg-warning "placement" } |
| |
| new (&c) char [2]; // { dg-warning "placement" } |
| new (&c) char [sizeof c + 1]; // { dg-warning "placement" } |
| new (&c) char [1][2]; // { dg-warning "placement" } |
| new (&c) char [2][1]; // { dg-warning "placement" } |
| new (&c) char [n][1]; |
| new (&c) char [n][2]; // { dg-warning "placement" } |
| new (&c) char [3]; // { dg-warning "placement" } |
| new (&c) char [3][1]; // { dg-warning "placement" } |
| new (&c) char [1][3]; // { dg-warning "placement" } |
| new (&c) char [4][1]; // { dg-warning "placement" } |
| new (&c) char [1][4]; // { dg-warning "placement" } |
| |
| // Casts must not suppress it. |
| new ((void*)&c) char [2]; // { dg-warning "placement" } |
| new ((char*)&c) char [3]; // { dg-warning "placement" } |
| |
| new (static_cast<void*>(&c)) char [4]; // { dg-warning "placement" } |
| new (reinterpret_cast<char*>(&c)) char [5]; // { dg-warning "placement" } |
| |
| new (&c + 0) char [2]; // { dg-warning "placement" } |
| new (&c + 0) char [3]; // { dg-warning "placement" } |
| new (&c + 0) char [4]; // { dg-warning "placement" } |
| |
| new (&c + 1) char [2]; // { dg-warning "placement" } |
| new (&c + 1) char [3]; // { dg-warning "placement" } |
| new (&c + 1) char [4]; // { dg-warning "placement" } |
| |
| new (&c + N0) char [1]; |
| new (&c + N1) char [2]; // { dg-warning "placement" } |
| |
| // Warn even though n is unknown since c is too small for char[2] |
| // regardless of the value of n. |
| new (&c + n) char [2]; // { dg-warning "placement" } |
| |
| new (ac2) char [1]; |
| new (ac2) char [1][1]; |
| new (ac2) char [1][2]; |
| new (ac2) char [2][1]; |
| new (ac2) char [1][3]; // { dg-warning "placement" } |
| new (ac2) char [2][2]; // { dg-warning "placement" } |
| new (ac2) char [3][1]; // { dg-warning "placement" } |
| |
| new (ac2 + N0) char [1][1]; |
| new (ac2 + N0) char [1][2]; |
| new (ac2 + N1) char [1][2]; // { dg-warning "placement" } |
| new (ac2 + N1) char [2][1]; // { dg-warning "placement" } |
| new (ac2 + N2) char [1][1]; // { dg-warning "placement" } |
| new (ac2 + N2) char [1][2]; // { dg-warning "placement" } |
| new (ac2 + N2) char [2][1]; // { dg-warning "placement" } |
| new (ac2 + N2) char [2][2]; // { dg-warning "placement" } |
| |
| new (ac8) char [1]; |
| new (ac8) char [2][2]; |
| new (ac8) char [2][3]; |
| new (ac8) char [2][4]; |
| new (ac8) char [2][5]; // { dg-warning "placement" } |
| new (ac8) char [2][2][2]; |
| new (ac8) char [2][2][3]; // { dg-warning "placement" } |
| |
| new (&c) int32_t; // { dg-warning "placement" } |
| |
| new (&ac1) int32_t; // { dg-warning "placement" } |
| new (&ac2) int32_t; // { dg-warning "placement" } |
| new (&ac3) int32_t; // { dg-warning "placement" } |
| new (&ac4) int32_t; |
| |
| // Constructing at an address of an array element. |
| new (&ac1 [0]) int32_t; // { dg-warning "placement" } |
| new (&ac2 [0]) int32_t; // { dg-warning "placement" } |
| new (&ac3 [0]) int32_t; // { dg-warning "placement" } |
| new (&ac4 [0]) int32_t; |
| |
| // ...plus or minus a constant offset. |
| new (&ac1 [0] + 0) int32_t; // { dg-warning "placement" } |
| new (&ac2 [0] + 0) int32_t; // { dg-warning "placement" } |
| new (&ac3 [0] + 0) int32_t; // { dg-warning "placement" } |
| new (&ac4 [0] + 0) int32_t; |
| new (&ac4 [1] + 0) int32_t; // { dg-warning "placement" } |
| new (&ac4 [1] - 1) int32_t; |
| new (&ac4 [2] - 1) int32_t; // { dg-warning "placement" } |
| new (&ac4 [2] - 2) int32_t; |
| new (&ac4 [3] - 1) int32_t; // { dg-warning "placement" } |
| new (&ac4 [3] - 2) int32_t; // { dg-warning "placement" } |
| new (&ac4 [3] - 3) int32_t; |
| new (&ac4 [4] - 1) int32_t; // { dg-warning "placement" } |
| new (&ac4 [4] - 2) int32_t; // { dg-warning "placement" } |
| new (&ac4 [4] - 3) int32_t; // { dg-warning "placement" } |
| new (&ac4 [4] - 4) int32_t; |
| |
| new (&ac1 [0] + 1) int32_t; // { dg-warning "placement" } |
| new (&ac2 [0] + 1) int32_t; // { dg-warning "placement" } |
| new (&ac3 [0] + 1) int32_t; // { dg-warning "placement" } |
| new (&ac4 [0] + 1) int32_t; // { dg-warning "placement" } |
| |
| new (&ac3 [0] + n) int32_t; // { dg-warning "placement" } |
| new (&ac4 [0] + n) int32_t; // no warning (n could be zero) |
| new (&ac4 [1] + n) int32_t; // no warning (n could be negative) |
| new (&ac4 [2] + n) int32_t; // ditto |
| new (&ac4 [3] + n) int32_t; // ditto |
| new (&ac4 [4] + n) int32_t; // ditto |
| new (&ac4 [4] - n) int32_t; // (or positive) |
| |
| new (&c + 0) int32_t; // { dg-warning "placement" } |
| new (&c + 1) int32_t; // { dg-warning "placement" } |
| |
| // Constructing at an offset into the address of an array. |
| new (&ac1 + 0) int32_t; // { dg-warning "placement" } |
| new (&ac1 + 1) int32_t; // { dg-warning "placement" } |
| new (&ac1 + n) int32_t; // { dg-warning "placement" } |
| new (&ac2 + 0) int32_t; // { dg-warning "placement" } |
| new (&ac2 + 1) int32_t; // { dg-warning "placement" } |
| new (&ac2 + n) int32_t; // { dg-warning "placement" } |
| new (&ac3 + 0) int32_t; // { dg-warning "placement" } |
| new (&ac3 + 1) int32_t; // { dg-warning "placement" } |
| |
| // Even though n below is uknown an array of 3 bytes isn't large |
| // enugh for an int32_t. |
| new (&ac3 + n) int32_t; // { dg-warning "placement" } |
| |
| new (&ac4 + 0) int32_t; |
| new (&ac4 + 1) int32_t; // { dg-warning "placement" } |
| new (&ac4 + n) int32_t; // no warning (n could be zero) |
| |
| // Constructing in an array object. |
| new (ac1) int32_t; // { dg-warning "placement" } |
| new (ac2) int32_t; // { dg-warning "placement" } |
| new (ac3) int32_t; // { dg-warning "placement" } |
| new (ac4) int32_t; |
| new (ac5) int32_t; |
| new (ac5 + 0) int32_t; |
| new (ac5 + 1) int32_t; |
| new (ac5 + n) int32_t; // no warning (n could be zero) |
| new (ac5 + 2) int32_t; // { dg-warning "placement" } |
| new (ac5 + 3) int32_t; // { dg-warning "placement" } |
| new (ac5 + 4) int32_t; // { dg-warning "placement" } |
| new (ac5 + 5) int32_t; // { dg-warning "placement" } |
| |
| new (ac1_1) char; |
| new (ac1_1) char[1]; |
| new (ac1_1) char[n]; // no warning (n is unknown) |
| new (ac1_1) char[2]; // { dg-warning "placement" } |
| new (ac1_1) char[3]; // { dg-warning "placement" } |
| |
| new (ac1_2) char; |
| new (ac1_2) char[1]; |
| new (ac1_2) char[2]; |
| new (ac1_2) char[3]; // { dg-warning "placement" } |
| |
| new (ac2_1) char; |
| new (ac2_1) char[1]; |
| new (ac2_1) char[2]; |
| new (ac2_1) char[3]; // { dg-warning "placement" } |
| |
| new (ac2_2) char; |
| new (ac2_2) char[1]; |
| new (ac2_2) char[2]; |
| new (ac2_2) char[2][2]; |
| |
| // Even though n below is uknown it can't meaningfully be zero |
| // (even if zero-size arrays are allowed as an extension, the size |
| // they are allocated in by placement new is zero). |
| new (ac1_1) char[n][2]; // { dg-warning "placement" } |
| new (ac2_2) char[3]; |
| new (ac2_2) char[3][1]; |
| new (ac2_2) char[3][2]; // { dg-warning "placement" } |
| new (ac2_2) char[4]; |
| new (ac2_2) char[4][1]; |
| new (ac2_2) char[4][2]; // { dg-warning "placement" } |
| new (ac2_2) char[5]; // { dg-warning "placement" } |
| |
| new (&s) int32_t; // { dg-warning "placement" } |
| new (&as1) int32_t; // { dg-warning "placement" } |
| new (&as2) int32_t; |
| |
| new (as1) int32_t; // { dg-warning "placement" } |
| new (as2) int32_t; |
| |
| new (&sc.c) int32_t; // { dg-warning "placement" } |
| new (&sac1.ac) int32_t; // { dg-warning "placement" } |
| new (&sac2.ac) int32_t; // { dg-warning "placement" } |
| new (&sac3.ac) int32_t; // { dg-warning "placement" } |
| new (&sac4.ac) int32_t; |
| |
| new (sc.pc) char; |
| new (sc.pc) int32_t; |
| new (sc.pc) int32_t[1024]; |
| new (sc.pc + 0) int32_t; |
| new (sc.pc + 0) int32_t[2048]; |
| new (sc.pv) int32_t; |
| new (sc.pv) char[1024]; |
| |
| new (sac1.ac) int32_t; // { dg-warning "placement" } |
| new (sac2.ac) int32_t; // { dg-warning "placement" } |
| new (sac3.ac) int32_t; // { dg-warning "placement" } |
| new (sac4.ac) int32_t; |
| |
| new (&ssc.sc) SSC; // { dg-warning "placement" } |
| new (&ssac1.sac) int32_t; // { dg-warning "placement" } |
| new (&ssac2.sac) int32_t; // { dg-warning "placement" } |
| new (&ssac3.sac) int32_t; // { dg-warning "placement" } |
| new (&ssac4.sac) int32_t; |
| |
| new (&sssac4_2) char[sizeof sssac4_2]; |
| new (&sssac4_2) char[sizeof sssac4_2 + 1]; // { dg-warning "placement" } |
| |
| // taking the address of a temporary is allowed with -fpermissive |
| new (&fsc ().c) int32_t; // { dg-warning "18:taking address|placement" } |
| new (&fasc1 ().ac) int32_t; // { dg-warning "20:taking address|placement" } |
| new (&fasc2 ().ac) int32_t; // { dg-warning "20:taking address|placement" } |
| new (&fasc3 ().ac) int32_t; // { dg-warning "20:taking address|placement" } |
| new (&fasc4 ().ac) int32_t; // { dg-warning "20:taking address|placement" } |
| |
| new (&uac1) int32_t; // { dg-warning "placement" } |
| new (&uac2) int32_t; // { dg-warning "placement" } |
| new (&uac3) int32_t; // { dg-warning "placement" } |
| new (&uac4) int32_t; |
| new (&uac4 + 1) int32_t; // { dg-warning "placement" } |
| |
| new (&uac1.c) int32_t; // { dg-warning "placement" } |
| new (&uac2.c) int32_t; // { dg-warning "placement" } |
| new (&uac3.c) int32_t; // { dg-warning "placement" } |
| |
| /* The following isn't diagnosed (anymore) for consistency with |
| the middle end where members of unions are considered to extend |
| to the end of the enclosing object. |
| See gcc.dg/Wstringop-overflow-60.c for the middle end test. */ |
| new (&uac4.c) int32_t; |
| |
| new (&uac4.c + 1) int32_t; // { dg-warning "placement" } |
| } |
| |
| |
| struct S { char c [2]; }; |
| |
| // Verify the full text of the warning message. |
| static __attribute__ ((used)) |
| void test_message (int32_t i) |
| { |
| char a [2]; |
| |
| // The exact sizes of both the buffer and the type are known. |
| new (a + 1) S; // { dg-warning "placement new constructing an object of type .S. and size .2. in a region of type .char \\\[2\\\]. and size .1." } |
| |
| // The buffer size is known but only the size of the type whose |
| // objects are being constructed is known, not their number. While |
| // in theory it could be zero, it practice likely never will be so |
| // the potential false positive is acceptable. |
| new (a + 1) S [i]; // { dg-warning "placement new constructing an array of objects of type .S. and size .2. in a region of type .char \\\[2\\\]. and size .1." } |
| |
| // The exact amount of space in the buffer isn't known, only its |
| // maximum is. The exact size of the array being created is known. |
| new (a + i) S [2]; // { dg-warning "placement new constructing an object of type .S \\\[2\\\]. and size .4. in a region of type .char \\\[2\\\]. and size at most .2." } |
| } |
| |
| |
| struct ClassWithMemberNew { |
| struct Object { int32_t i; } *pobj; |
| unsigned nobj; |
| |
| ClassWithMemberNew (); |
| void foo (); |
| |
| void* operator new (size_t, void*); |
| void* operator new[] (size_t, void*); |
| }; |
| |
| void ClassWithMemberNew::foo() |
| { |
| for (unsigned i = 0; i != nobj; ++i) |
| new (pobj + i) Object (); |
| } |
| |
| |
| struct ClassWithGlobalNew { |
| int32_t a [4]; |
| ClassWithGlobalNew (); |
| }; |
| |
| void* operator new (size_t, ClassWithGlobalNew*); |
| void* operator new[] (size_t, ClassWithGlobalNew*); |
| |
| void test_user_defined_placement_new () |
| { |
| { |
| ClassWithMemberNew x; |
| |
| // Expect no diagnostics for placement new expressions with types |
| // with their own placement operator new since the semantics of |
| // the operator aren't known. |
| new (&c) ClassWithMemberNew; |
| new (&x) ClassWithMemberNew[2]; |
| } |
| |
| { |
| ClassWithGlobalNew x; |
| |
| new (&c) ClassWithGlobalNew; // { dg-warning "placement" } |
| new (&x) ClassWithGlobalNew[2]; |
| } |
| } |
| |
| extern char extbuf[]; |
| |
| template <class> struct TemplateClass { char c; }; |
| |
| // Declare a specialization but don't provide a definition. |
| template <> struct TemplateClass<void>; |
| |
| // Declare an object of an explicit specialization of an unknown size. |
| extern TemplateClass<void> exttempl_void; |
| |
| // Verify that no warning is issued when placement new is called with |
| // an extern buffer of unknown size (and the case is handled gracefully |
| // and doesn't cause an ICE). |
| static __attribute__ ((used)) |
| void test_extern_buffer_of_unknown_size () |
| { |
| new (extbuf) int32_t (); |
| new (extbuf) int32_t [1024]; |
| |
| new (&exttempl_void) int32_t (); |
| new (&exttempl_void) int32_t [1024]; |
| } |
| |
| extern char extbuf_size_int [sizeof (int32_t)]; |
| |
| extern TemplateClass<int32_t> exttempl; |
| |
| // Verify that a warning is issued as expected when placement new is |
| // called with an extern buffer of known size (and the case is handled |
| // gracefully and doesn't cause an ICE). |
| static __attribute__ ((used)) |
| void test_extern_buffer () |
| { |
| new (extbuf_size_int) int32_t (); |
| new (extbuf_size_int) int32_t [1]; |
| |
| struct S { int32_t a [2]; }; |
| |
| new (extbuf_size_int) S; // { dg-warning "placement" } |
| new (extbuf_size_int) int32_t [2]; // { dg-warning "placement" } |
| |
| new (&exttempl) int32_t (); // { dg-warning "placement" } |
| new (&exttempl) int32_t [1024]; // { dg-warning "placement" } |
| } |