aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-12-14 13:30:00 -0700
committerMartin Sebor <msebor@redhat.com>2020-12-14 13:30:00 -0700
commitfe7f75cf16783589eedbab597e6d0b8d35d7e470 (patch)
tree7fec98daa8cd2d99d08d302f753fb7416f3e901c /gcc/tree.c
parente63ae8c083a3218400206b80d4eedd9950fc5d3f (diff)
downloadgcc-fe7f75cf16783589eedbab597e6d0b8d35d7e470.zip
gcc-fe7f75cf16783589eedbab597e6d0b8d35d7e470.tar.gz
gcc-fe7f75cf16783589eedbab597e6d0b8d35d7e470.tar.bz2
Correct/improve maybe_emit_free_warning (PR middle-end/98166, PR c++/57111, PR middle-end/98160).
Resolves: PR middle-end/98166 - bogus -Wmismatched-dealloc on user-defined allocator and inlining PR c++/57111 - 57111 - Generalize -Wfree-nonheap-object to delete PR middle-end/98160 - ICE in default_tree_printer at gcc/tree-diagnostic.c:270 gcc/ChangeLog: PR middle-end/98166 PR c++/57111 PR middle-end/98160 * builtins.c (check_access): Call tree_inlined_location fndecl_alloc_p): Handle BUILT_IN_ALIGNED_ALLOC and BUILT_IN_GOMP_ALLOC. call_dealloc_p): Remove unused function. (new_delete_mismatch_p): Call valid_new_delete_pair_p and rework. (matching_alloc_calls_p): Handle built-in deallocation functions. (warn_dealloc_offset): Corrct the handling of user-defined operators delete. (maybe_emit_free_warning): Avoid assuming expression is a decl. Simplify. * doc/extend.texi (attribute malloc): Update. * tree-ssa-dce.c (valid_new_delete_pair_p): Factor code out into valid_new_delete_pair_p in tree.c. * tree.c (tree_inlined_location): Define new function. (valid_new_delete_pair_p): Define. * tree.h (tree_inlined_location): Declare. (valid_new_delete_pair_p): Declare. gcc/c-family/ChangeLog: PR middle-end/98166 PR c++/57111 PR middle-end/98160 * c-attribs.c (maybe_add_noinline): New function. (handle_malloc_attribute): Call it. Use ATTR_FLAG_INTERNAL. Implicitly add attribute noinline to functions not declared inline and warn on those. libstdc++-v3/ChangeLog: * testsuite/ext/vstring/requirements/exception/basic.cc: Suppress a false positive warning. * testsuite/ext/vstring/requirements/exception/propagation_consistent.cc: Same. gcc/testsuite/ChangeLog: PR middle-end/98166 PR c++/57111 PR middle-end/98160 * g++.dg/warn/Wmismatched-dealloc-2.C: Adjust test of expected warning. * g++.dg/warn/Wmismatched-new-delete.C: Same. * gcc.dg/Wmismatched-dealloc.c: Same. * c-c++-common/Wfree-nonheap-object-2.c: New test. * c-c++-common/Wfree-nonheap-object-3.c: New test. * c-c++-common/Wfree-nonheap-object.c: New test. * c-c++-common/Wmismatched-dealloc.c: New test. * g++.dg/warn/Wfree-nonheap-object-3.C: New test. * g++.dg/warn/Wfree-nonheap-object-4.C: New test. * g++.dg/warn/Wmismatched-dealloc-2.C: New test. * g++.dg/warn/Wmismatched-new-delete-2.C: New test. * g++.dg/warn/Wmismatched-new-delete.C: New test. * gcc.dg/Wmismatched-dealloc-2.c: New test. * gcc.dg/Wmismatched-dealloc-3.c: New test. * gcc.dg/Wmismatched-dealloc.c: New test.
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c103
1 files changed, 102 insertions, 1 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 9b2ecb3..5fd9da3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -12610,8 +12610,40 @@ tree_nonartificial_location (tree exp)
return EXPR_LOCATION (exp);
}
+/* Return the location into which EXP has been inlined. Analogous
+ to tree_nonartificial_location() above but not limited to artificial
+ functions declared inline. If SYSTEM_HEADER is true, return
+ the macro expansion point of the location if it's in a system header */
-/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq
+location_t
+tree_inlined_location (tree exp, bool system_header /* = true */)
+{
+ location_t loc = UNKNOWN_LOCATION;
+
+ tree block = TREE_BLOCK (exp);
+
+ while (block && TREE_CODE (block) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (block))
+ {
+ tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+ if (TREE_CODE (ao) == FUNCTION_DECL)
+ loc = BLOCK_SOURCE_LOCATION (block);
+ else if (TREE_CODE (ao) != BLOCK)
+ break;
+
+ block = BLOCK_SUPERCONTEXT (block);
+ }
+
+ if (loc == UNKNOWN_LOCATION)
+ loc = EXPR_LOCATION (exp);
+
+ if (system_header)
+ return expansion_point_location_if_in_system_header (loc);
+
+ return loc;
+}
+
+/* These are the hash table functions for the hash table of OPTIMIZATION_NODE
nodes. */
/* Return the hash code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */
@@ -15386,6 +15418,75 @@ 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. */
+
+bool
+valid_new_delete_pair_p (tree new_asm, tree delete_asm)
+{
+ 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);
+
+ if (new_len < 5 || delete_len < 6)
+ return false;
+ if (new_name[0] == '_')
+ ++new_name, --new_len;
+ if (new_name[0] == '_')
+ ++new_name, --new_len;
+ if (delete_name[0] == '_')
+ ++delete_name, --delete_len;
+ if (delete_name[0] == '_')
+ ++delete_name, --delete_len;
+ if (new_len < 4 || delete_len < 5)
+ return false;
+ /* *_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;
+ /* _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'))
+ return false;
+ /* 'j', 'm' and 'y' correspond to size_t. */
+ if (new_name[3] != 'j' && new_name[3] != 'm' && new_name[3] != 'y')
+ return false;
+ if (delete_name[3] != 'P' || delete_name[4] != 'v')
+ return false;
+ if (new_len == 4
+ || (new_len == 18 && !memcmp (new_name + 4, "RKSt9nothrow_t", 14)))
+ {
+ /* _ZnXY or _ZnXYRKSt9nothrow_t matches
+ _ZdXPv, _ZdXPvY and _ZdXPvRKSt9nothrow_t. */
+ if (delete_len == 5)
+ return true;
+ if (delete_len == 6 && delete_name[5] == new_name[3])
+ return true;
+ if (delete_len == 19 && !memcmp (delete_name + 5, "RKSt9nothrow_t", 14))
+ return true;
+ }
+ else if ((new_len == 19 && !memcmp (new_name + 4, "St11align_val_t", 15))
+ || (new_len == 33
+ && !memcmp (new_name + 4, "St11align_val_tRKSt9nothrow_t", 29)))
+ {
+ /* _ZnXYSt11align_val_t or _ZnXYSt11align_val_tRKSt9nothrow_t matches
+ _ZdXPvSt11align_val_t or _ZdXPvYSt11align_val_t or or
+ _ZdXPvSt11align_val_tRKSt9nothrow_t. */
+ if (delete_len == 20 && !memcmp (delete_name + 5, "St11align_val_t", 15))
+ return true;
+ if (delete_len == 21
+ && delete_name[5] == new_name[3]
+ && !memcmp (delete_name + 6, "St11align_val_t", 15))
+ return true;
+ if (delete_len == 34
+ && !memcmp (delete_name + 5, "St11align_val_tRKSt9nothrow_t", 29))
+ return true;
+ }
+ return false;
+}
+
#if CHECKING_P
namespace selftest {