mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 03:20:27 +08:00
Teach compute_objsize about placement new [PR100876].
Resolves: PR c++/100876 - -Wmismatched-new-delete should understand placement new when it's not inlined gcc/ChangeLog: PR c++/100876 * builtins.c (gimple_call_return_array): Check for attribute fn spec. Handle calls to placement new. (ndecl_dealloc_argno): Avoid placement delete. gcc/testsuite/ChangeLog: PR c++/100876 * g++.dg/warn/Wmismatched-new-delete-4.C: New test. * g++.dg/warn/Wmismatched-new-delete-5.C: New test. * g++.dg/warn/Wstringop-overflow-7.C: New test. * g++.dg/warn/Wfree-nonheap-object-6.C: New test. * g++.dg/analyzer/placement-new.C: Prune out expected warning.
This commit is contained in:
parent
f9598d89a9
commit
d9f1466f88
@ -5159,11 +5159,42 @@ static tree
|
||||
gimple_call_return_array (gimple *stmt, offset_int offrng[2],
|
||||
range_query *rvals)
|
||||
{
|
||||
if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
|
||||
|| gimple_call_num_args (stmt) < 1)
|
||||
{
|
||||
/* Check for attribute fn spec to see if the function returns one
|
||||
of its arguments. */
|
||||
attr_fnspec fnspec = gimple_call_fnspec (as_a <gcall *>(stmt));
|
||||
unsigned int argno;
|
||||
if (fnspec.returns_arg (&argno))
|
||||
{
|
||||
offrng[0] = offrng[1] = 0;
|
||||
return gimple_call_arg (stmt, argno);
|
||||
}
|
||||
}
|
||||
|
||||
if (gimple_call_num_args (stmt) < 1)
|
||||
return NULL_TREE;
|
||||
|
||||
tree fn = gimple_call_fndecl (stmt);
|
||||
if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
|
||||
{
|
||||
/* See if this is a call to placement new. */
|
||||
if (!fn
|
||||
|| !DECL_IS_OPERATOR_NEW_P (fn)
|
||||
|| DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fn))
|
||||
return NULL_TREE;
|
||||
|
||||
tree fname = DECL_ASSEMBLER_NAME (fn);
|
||||
if (!id_equal (fname, "_ZnwmPv") // ordinary form
|
||||
&& !id_equal (fname, "_ZnamPv")) // array form
|
||||
return NULL_TREE;
|
||||
|
||||
if (gimple_call_num_args (stmt) != 2)
|
||||
return NULL_TREE;
|
||||
|
||||
offrng[0] = offrng[1] = 0;
|
||||
return gimple_call_arg (stmt, 1);
|
||||
}
|
||||
|
||||
switch (DECL_FUNCTION_CODE (fn))
|
||||
{
|
||||
case BUILT_IN_MEMCPY:
|
||||
@ -13285,7 +13316,17 @@ fndecl_dealloc_argno (tree fndecl)
|
||||
{
|
||||
/* A call to operator delete isn't recognized as one to a built-in. */
|
||||
if (DECL_IS_OPERATOR_DELETE_P (fndecl))
|
||||
return 0;
|
||||
{
|
||||
if (DECL_IS_REPLACEABLE_OPERATOR (fndecl))
|
||||
return 0;
|
||||
|
||||
/* Avoid placement delete that's not been inlined. */
|
||||
tree fname = DECL_ASSEMBLER_NAME (fndecl);
|
||||
if (id_equal (fname, "_ZdlPvS_") // ordinary form
|
||||
|| id_equal (fname, "_ZdaPvS_")) // array form
|
||||
return UINT_MAX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Handle user-defined functions with attribute malloc? Handle
|
||||
known non-built-ins like fopen? */
|
||||
|
@ -24,3 +24,5 @@ void test_3 (void)
|
||||
int *p = new(buf) int (42);
|
||||
delete p; // { dg-warning "memory not on the heap" }
|
||||
}
|
||||
|
||||
// { dg-prune-output "-Wfree-nonheap-object" }
|
||||
|
45
gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-6.C
Normal file
45
gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-6.C
Normal file
@ -0,0 +1,45 @@
|
||||
/* { dg-do compile }
|
||||
{ dg-options "-O0 -Wall" } */
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
# define noexcept throw ()
|
||||
#endif
|
||||
|
||||
void* operator new (__SIZE_TYPE__, void* __p) noexcept;
|
||||
void operator delete (void*, void*);
|
||||
|
||||
void* operator new[] (__SIZE_TYPE__, void* __p) noexcept;
|
||||
void operator delete[] (void*, void*) noexcept;
|
||||
|
||||
struct A { A (); ~A (); int i; };
|
||||
|
||||
extern void *p;
|
||||
|
||||
void nowarn_placement_new ()
|
||||
{
|
||||
char a[sizeof (A)];
|
||||
p = new (a) A (); // { dg-bogus "-Wfree-nonheap-object" }
|
||||
}
|
||||
|
||||
|
||||
void warn_placement_new ()
|
||||
{
|
||||
char a[sizeof (A)];
|
||||
p = new (a + 1) A (); // { dg-warning "\\\[-Wplacement-new" }
|
||||
// { dg-bogus "-Wfree-nonheap-object" "bogus" { target *-*-* } .-1 }
|
||||
}
|
||||
|
||||
|
||||
void nowarn_placement_new_array ()
|
||||
{
|
||||
char a[sizeof (A)];
|
||||
p = new (a) A[1]; // { dg-bogus "-Wfree-nonheap-object" }
|
||||
}
|
||||
|
||||
|
||||
void warn_placement_new_array ()
|
||||
{
|
||||
char a[sizeof (A)];
|
||||
p = new (a + 1) A[1]; // { dg-warning "\\\[-Wplacement-new" }
|
||||
// { dg-bogus "-Wfree-nonheap-object" "bogus" { target *-*-* } .-1 }
|
||||
}
|
37
gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-4.C
Normal file
37
gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-4.C
Normal file
@ -0,0 +1,37 @@
|
||||
/* PR c++/100876 - -Wmismatched-new-delete should either look through
|
||||
or ignore placement new
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O0 -Wall" } */
|
||||
|
||||
extern "C" {
|
||||
void* malloc (__SIZE_TYPE__);
|
||||
void free (void*);
|
||||
}
|
||||
|
||||
void* operator new (__SIZE_TYPE__, void*);
|
||||
void* operator new[] (__SIZE_TYPE__, void*);
|
||||
|
||||
void nowarn_placement_new ()
|
||||
{
|
||||
free (new (malloc (sizeof (int))) int ()); // { dg-bogus "-Wmismatched-new-delete" }
|
||||
}
|
||||
|
||||
void nowarn_placement_array_new ()
|
||||
{
|
||||
free (new (malloc (sizeof (int) * 2)) int[2]); // { dg-bogus "-Wmismatched-new-delete" }
|
||||
}
|
||||
|
||||
|
||||
void warn_placement_new ()
|
||||
{
|
||||
void *p = malloc (sizeof (int));
|
||||
int *q = new (p) int ();
|
||||
delete q; // { dg-warning "-Wmismatched-new-delete" }
|
||||
}
|
||||
|
||||
void warn_placement_array_new ()
|
||||
{
|
||||
void *p = malloc (sizeof (int));
|
||||
int *q = new (p) int[2];
|
||||
delete q; // { dg-warning "-Wmismatched-new-delete" }
|
||||
}
|
37
gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C
Normal file
37
gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C
Normal file
@ -0,0 +1,37 @@
|
||||
/* PR c++/100876 - -Wmismatched-new-delete should either look through
|
||||
or ignore placement new
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall" } */
|
||||
|
||||
extern "C" {
|
||||
void* malloc (__SIZE_TYPE__);
|
||||
void free (void*);
|
||||
}
|
||||
|
||||
inline void* operator new (__SIZE_TYPE__, void *p) { return p; }
|
||||
inline void* operator new[] (__SIZE_TYPE__, void *p) { return p; }
|
||||
|
||||
void nowarn_placement_new ()
|
||||
{
|
||||
free (new (malloc (sizeof (int))) int ()); // { dg-bogus "-Wmismatched-new-delete" }
|
||||
}
|
||||
|
||||
void nowarn_placement_array_new ()
|
||||
{
|
||||
free (new (malloc (sizeof (int) * 2)) int[2]); // { dg-bogus "-Wmismatched-new-delete" }
|
||||
}
|
||||
|
||||
|
||||
void warn_placement_new ()
|
||||
{
|
||||
void *p = malloc (sizeof (int));
|
||||
int *q = new (p) int ();
|
||||
delete q; // { dg-warning "-Wmismatched-new-delete" }
|
||||
}
|
||||
|
||||
void warn_placement_array_new ()
|
||||
{
|
||||
void *p = malloc (sizeof (int));
|
||||
int *q = new (p) int[2];
|
||||
delete q; // { dg-warning "-Wmismatched-new-delete" }
|
||||
}
|
42
gcc/testsuite/g++.dg/warn/Wstringop-overflow-7.C
Normal file
42
gcc/testsuite/g++.dg/warn/Wstringop-overflow-7.C
Normal file
@ -0,0 +1,42 @@
|
||||
/* PR c++/100876 - -Wmismatched-new-delete should either look through
|
||||
or ignore placement new
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O0 -Wall -Wno-array-bounds" } */
|
||||
|
||||
inline void* operator new (__SIZE_TYPE__, void *p) { return p; }
|
||||
inline void* operator new[] (__SIZE_TYPE__, void *p) { return p; }
|
||||
|
||||
void* nowarn_placement_new_memset ()
|
||||
{
|
||||
struct S { int i; };
|
||||
void *p = __builtin_malloc (sizeof (S));
|
||||
S *q = new (p) S;
|
||||
__builtin_memset (q, 0, sizeof (S));
|
||||
return q;
|
||||
}
|
||||
|
||||
void* warn_placement_new_memset ()
|
||||
{
|
||||
struct S { int i; };
|
||||
void *p = __builtin_malloc (sizeof (S));
|
||||
S *q = new (p) S;
|
||||
__builtin_memset (q, 0, sizeof (S) + 1); // { dg-warning "\\\[-Wstringop-overflow" }
|
||||
return q;
|
||||
}
|
||||
|
||||
void* nowarn_placement_new_array_strncpy (const char *s)
|
||||
{
|
||||
void *p = __builtin_malloc (5);
|
||||
char *q = new (p) char[5];
|
||||
__builtin_strncpy (q, s, 5);
|
||||
return q;
|
||||
|
||||
}
|
||||
|
||||
void* warn_placement_new_array_strncpy (const char *s)
|
||||
{
|
||||
void *p = __builtin_malloc (4);
|
||||
char *q = new (p) char[5];
|
||||
__builtin_strncpy (q, s, 5); // { dg-warning "\\\[-Wstringop-overflow" }
|
||||
return q;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user