public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-2908] Diagnose mismatches between array and scalar new and delete [PR101791].
@ 2021-08-14 19:27 Martin Sebor
0 siblings, 0 replies; only message in thread
From: Martin Sebor @ 2021-08-14 19:27 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:96194a07bdbc57dd9733892a791d87dbe25f0802
commit r12-2908-g96194a07bdbc57dd9733892a791d87dbe25f0802
Author: Martin Sebor <msebor@redhat.com>
Date: Sat Aug 14 13:25:41 2021 -0600
Diagnose mismatches between array and scalar new and delete [PR101791].
Resolves:
PR middle-end/101791 - missing warning on a mismatch between scalar and array forms of new and delete
gcc/ChangeLog:
PR middle-end/101791
* gimple-ssa-warn-access.cc (new_delete_mismatch_p): Use new argument
to valid_new_delete_pair_p.
* tree.c (valid_new_delete_pair_p): Add argument.
* tree.h (valid_new_delete_pair_p): Same.
gcc/testsuite/ChangeLog:
PR middle-end/101791
* g++.dg/warn/Wmismatched-new-delete-6.C: New test.
* g++.dg/warn/Wmismatched-new-delete-7.C: New test.
Diff:
---
gcc/gimple-ssa-warn-access.cc | 9 +-
.../g++.dg/warn/Wmismatched-new-delete-6.C | 158 +++++++++++++++++++++
.../g++.dg/warn/Wmismatched-new-delete-7.C | 91 ++++++++++++
gcc/tree.c | 28 +++-
gcc/tree.h | 4 +-
5 files changed, 284 insertions(+), 6 deletions(-)
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index a4559ddb5b3..93f43b711e2 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -1782,9 +1782,14 @@ new_delete_mismatch_p (tree new_decl, tree delete_decl)
/* valid_new_delete_pair_p() returns a conservative result (currently
it only handles global operators). A true result is reliable but
- a false result doesn't necessarily mean the operators don't match. */
- if (valid_new_delete_pair_p (new_name, delete_name))
+ a false result doesn't necessarily mean the operators don't match
+ unless CERTAIN is set. */
+ bool certain;
+ if (valid_new_delete_pair_p (new_name, delete_name, &certain))
return false;
+ /* CERTAIN is set when the negative result is certain. */
+ if (certain)
+ return true;
/* For anything not handled by valid_new_delete_pair_p() such as member
operators compare the individual demangled components of the mangled
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-6.C b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-6.C
new file mode 100644
index 00000000000..e19d00058b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-6.C
@@ -0,0 +1,158 @@
+/* PR middle-end/101791 - missing warning on a mismatch between scalar
+ and array forms of new and delete
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+namespace std
+{
+#if __cplusplus >= 201703L
+enum class align_val_t: size_t { };
+#else
+enum align_val_t { };
+#endif
+
+struct nothrow_t { };
+const nothrow_t nothrow = { };
+
+}
+
+void* operator new (size_t);
+void* operator new (size_t, std::align_val_t);
+void* operator new (size_t, std::nothrow_t) throw ();
+void* operator new (size_t, std::align_val_t, std::nothrow_t) throw ();
+
+void* operator new[] (size_t);
+void* operator new[] (size_t, std::align_val_t);
+void* operator new[] (size_t, std::nothrow_t) throw ();
+void* operator new[] (size_t, std::align_val_t, std::nothrow_t) throw ();
+
+void operator delete (void*);
+void operator delete (void*, size_t);
+void operator delete (void*, std::align_val_t);
+void operator delete (void*, size_t, std::align_val_t);
+void operator delete (void*, std::nothrow_t) throw ();
+void operator delete (void*, std::align_val_t, std::nothrow_t) throw ();
+
+void operator delete[] (void*);
+void operator delete[] (void*, size_t);
+void operator delete[] (void*, std::align_val_t);
+void operator delete[] (void*, size_t, std::align_val_t);
+void operator delete[] (void*, std::nothrow_t) throw ();
+void operator delete[] (void*, std::align_val_t, std::nothrow_t) throw ();
+
+
+void sink (void*, ...);
+
+
+void nowarn_scalar_scalar ()
+{
+ {
+ int *p = new int;
+ sink (p);
+ delete p;
+ }
+
+ {
+ int *p = new (std::align_val_t (8)) int;
+ sink (p);
+ delete p;
+ }
+
+ {
+ int *p = new (std::nothrow) int;
+ sink (p);
+ delete p;
+ }
+
+ {
+ int *p = new (std::align_val_t (8), std::nothrow) int;
+ sink (p);
+ delete p;
+ }
+}
+
+void nowarn_array_array ()
+{
+ {
+ int *p = new int[__LINE__];
+ sink (p);
+ delete[] p;
+ }
+
+ {
+ int *p = new (std::align_val_t (8)) int[__LINE__];
+ sink (p);
+ delete[] p;
+ }
+
+ {
+ int *p = new (std::nothrow) int[__LINE__];
+ sink (p);
+ delete[] p;
+ }
+
+ {
+ int *p = new (std::align_val_t (8), std::nothrow) int[__LINE__];
+ sink (p);
+ delete[] p;
+ }
+}
+
+
+
+void nowarn_scalar_array ()
+{
+ {
+ int *p = new int; // { dg-message "returned from" }
+ sink (p);
+ delete[] p; // { dg-warning "\\\[-Wmismatched-new-delete" }
+ }
+
+ {
+ int *p = new (std::align_val_t (8)) int;
+ sink (p);
+ delete[] p; // { dg-warning "\\\[-Wmismatched-new-delete" }
+ }
+
+ {
+ int *p = new (std::nothrow) int;
+ sink (p);
+ delete[] p; // { dg-warning "\\\[-Wmismatched-new-delete" }
+ }
+
+ {
+ int *p = new (std::align_val_t (8), std::nothrow) int;
+ sink (p);
+ delete[] p; // { dg-warning "\\\[-Wmismatched-new-delete" }
+ }
+}
+
+
+void nowarn_array_scalar ()
+{
+ {
+ int *p = new int[__LINE__];
+ sink (p);
+ delete p; // { dg-warning "\\\[-Wmismatched-new-delete" }
+ }
+
+ {
+ int *p = new (std::align_val_t (8)) int[__LINE__];
+ sink (p);
+ delete p; // { dg-warning "\\\[-Wmismatched-new-delete" }
+ }
+
+ {
+ int *p = new (std::nothrow) int[__LINE__];
+ sink (p);
+ delete p; // { dg-warning "\\\[-Wmismatched-new-delete" }
+ }
+
+ {
+ int *p = new (std::align_val_t (8), std::nothrow) int[__LINE__];
+ sink (p);
+ delete p; // { dg-warning "\\\[-Wmismatched-new-delete" }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-7.C b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-7.C
new file mode 100644
index 00000000000..67a5354b91d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-7.C
@@ -0,0 +1,91 @@
+/* PR middle-end/101791 - missing warning on a mismatch between scalar
+ and array forms of new and delete
+ Verify that likely safe calls to technically mismatched member operator
+ new and delete are not diagnosed. This test might need to be adjusted
+ if it turns out the assumptions GCC makes are overly conservative.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+namespace std
+{
+#if __cplusplus >= 201703L
+enum class align_val_t: size_t { };
+#else
+enum align_val_t { };
+#endif
+
+struct nothrow_t { };
+const nothrow_t nothrow = { };
+
+}
+
+void sink (void*, ...);
+
+struct X { } x;
+struct Y { } y;
+
+struct A
+{
+ void* operator new (size_t);
+ void* operator new (size_t, std::align_val_t);
+
+ void* operator new (size_t, X);
+ void* operator new (size_t, Y);
+
+ void* operator new (size_t, std::align_val_t, X);
+ void* operator new (size_t, std::nothrow_t, Y);
+
+ /* A single operator delete callable on the result of calls to any
+ of the operator new overloads above (this may be too optimistic). */
+ void operator delete (void*);
+};
+
+A* nowarn_align ()
+{
+ /* The following are likely okay given A's definition above but would
+ not be if A also defined an align_val_t overload of operator delete. */
+ A *p = new (std::align_val_t (8)) A;
+ delete p;
+
+ return new (std::align_val_t (16)) A;
+}
+
+A* nowarn_X ()
+{
+ /* The following are also likely okay given A's definition above but
+ also would not be if A also defined an overload of operator delete
+ for X. */
+ A *p = new (x) A;
+ delete p;
+ return new (x) A;
+}
+
+A* nowarn_Y ()
+{
+ // Same as above.
+ A *p = new (y) A;
+ delete p;
+ return new (y) A;
+}
+
+
+A* nowarn_align_X ()
+{
+ // Same as above.
+ A *p = new (std::align_val_t (32), x) A;
+ delete p;
+
+ return new (std::align_val_t (64), x) A;
+}
+
+
+A* nowarn_nothrow_Y ()
+{
+ // Same as above.
+ A *p = new (std::nothrow, y) A;
+ delete p;
+ return new (std::nothrow, y) A;
+}
+
diff --git a/gcc/tree.c b/gcc/tree.c
index a0ff79468eb..6ec8a9738c8 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -14314,17 +14314,28 @@ verify_type_context (location_t loc, type_context_kind context,
|| targetm.verify_type_context (loc, context, type, silent_p));
}
-/* Return that NEW_ASM and DELETE_ASM name a valid pair of new and
- delete operators. */
+/* Return true if NEW_ASM and DELETE_ASM name a valid pair of new and
+ delete operators. Return false if they may or may not name such
+ a pair and, when nonnull, set *PCERTAIN to true if they certainly
+ do not. */
bool
-valid_new_delete_pair_p (tree new_asm, tree delete_asm)
+valid_new_delete_pair_p (tree new_asm, tree delete_asm,
+ bool *pcertain /* = NULL */)
{
+ bool certain;
+ if (!pcertain)
+ pcertain = &certain;
+
const char *new_name = IDENTIFIER_POINTER (new_asm);
const char *delete_name = IDENTIFIER_POINTER (delete_asm);
unsigned int new_len = IDENTIFIER_LENGTH (new_asm);
unsigned int delete_len = IDENTIFIER_LENGTH (delete_asm);
+ /* The following failures are due to invalid names so they're not
+ considered certain mismatches. */
+ *pcertain = false;
+
if (new_len < 5 || delete_len < 6)
return false;
if (new_name[0] == '_')
@@ -14337,11 +14348,19 @@ valid_new_delete_pair_p (tree new_asm, tree delete_asm)
++delete_name, --delete_len;
if (new_len < 4 || delete_len < 5)
return false;
+
+ /* The following failures are due to names of user-defined operators
+ so they're also not considered certain mismatches. */
+
/* *_len is now just the length after initial underscores. */
if (new_name[0] != 'Z' || new_name[1] != 'n')
return false;
if (delete_name[0] != 'Z' || delete_name[1] != 'd')
return false;
+
+ /* The following failures are certain mismatches. */
+ *pcertain = true;
+
/* _Znw must match _Zdl, _Zna must match _Zda. */
if ((new_name[2] != 'w' || delete_name[2] != 'l')
&& (new_name[2] != 'a' || delete_name[2] != 'a'))
@@ -14380,6 +14399,9 @@ valid_new_delete_pair_p (tree new_asm, tree delete_asm)
&& !memcmp (delete_name + 5, "St11align_val_tRKSt9nothrow_t", 29))
return true;
}
+
+ /* The negative result is conservative. */
+ *pcertain = false;
return false;
}
diff --git a/gcc/tree.h b/gcc/tree.h
index c3f302a406a..a26500dca61 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5406,7 +5406,9 @@ extern bool gimple_canonical_types_compatible_p (const_tree, const_tree,
extern bool type_with_interoperable_signedness (const_tree);
extern bitmap get_nonnull_args (const_tree);
extern int get_range_pos_neg (tree);
-extern bool valid_new_delete_pair_p (tree, tree);
+
+/* Return true for a valid pair of new and delete operators. */
+extern bool valid_new_delete_pair_p (tree, tree, bool * = NULL);
/* Return simplified tree code of type that is used for canonical type
merging. */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-08-14 19:27 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-14 19:27 [gcc r12-2908] Diagnose mismatches between array and scalar new and delete [PR101791] Martin Sebor
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).