diff options
author | Martin Sebor <msebor@redhat.com> | 2020-12-14 13:30:00 -0700 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-12-14 13:30:00 -0700 |
commit | fe7f75cf16783589eedbab597e6d0b8d35d7e470 (patch) | |
tree | 7fec98daa8cd2d99d08d302f753fb7416f3e901c /gcc/tree.c | |
parent | e63ae8c083a3218400206b80d4eedd9950fc5d3f (diff) | |
download | gcc-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.c | 103 |
1 files changed, 102 insertions, 1 deletions
@@ -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 { |