From patchwork Fri Aug 2 20:36:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Arsen_Arsenovi=C4=87?= X-Patchwork-Id: 1968544 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aarsen.me header.i=@aarsen.me header.a=rsa-sha256 header.s=MBO0001 header.b=J1Nazp6V; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WbJYX50sVz1yZl for ; Sat, 3 Aug 2024 07:16:48 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D3CDC3858430 for ; Fri, 2 Aug 2024 21:16:46 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) by sourceware.org (Postfix) with ESMTPS id A618F3858D26 for ; Fri, 2 Aug 2024 21:16:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A618F3858D26 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=aarsen.me Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=aarsen.me ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A618F3858D26 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=80.241.56.151 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722633385; cv=none; b=BmJvOHHlkHxXpiIA1HVEF6Apj9uoCUOi495PdvjCopF/GMt9y3VHYQWu1Chdid3o/69IuasD3C0MAkCjV68SNO6tMfywayTUZk7NToZE0lY0MmhaDQ2DTGDvOQj3XBpsox3hwV+4FhtUJK+PFRo8pJMLBFuCGl8Yp7Hfrhhmrxw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722633385; c=relaxed/simple; bh=VOhnAhv1azubD3nvKZkBoUBj1woAnb4HdxlF0bbKFAk=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=PEYpIeRWtwStQhzjATlci8OojBLvfqebWhSzr/YXHLBEnldyaK8A9eNQd43ZpdVICKaASoTJBdXQRkxd4KFSW3ph1yt1vCuYzmX5sj40HYPtWk+UZvzcRvjVIjbqPaem6JOk9ZiPEfBkm5ww5Dj7soqhHgyC2kh0NBPwRmQ7McE= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smtp202.mailbox.org (smtp202.mailbox.org [10.196.197.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4WbJXz68zxz9sSR; Fri, 2 Aug 2024 23:16:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aarsen.me; s=MBO0001; t=1722633379; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=bKYNAVKBwO4NjiTWYaaxdjqwvVZNC4R76T3wBZLSRsE=; b=J1Nazp6VrAUM1obYVRZWBHEdUzsfQawtSqlHZkH1W8OLTllYne8QUwjA7x3gu6pJVM2nYQ onglqKmR4tAXWHEH20AITslnqxJAsTlPI+N62KLqaQz/EVqJgvrWhAYp9PkZEC/3fTLmbq SfMGey7N7kbYbfkP+ptW3HNVtheLzmAZAwqBROBULZCQkgoLsQQgii7yiktfRr/bJuivzU mhqHUr07c+JDemPDcI97erUQYaL0qQDC7rkPZZsylKEpb+Dp9XoYjEnr52hMkLNK3du1mr AEeIZYJjLjkYJXhpbWPC2iI99fcQM6UIE7qtLKBWCMEgLI0GUPUuZX5enMJBVQ== From: =?utf-8?q?Arsen_Arsenovi=C4=87?= To: gcc-patches@gcc.gnu.org Cc: =?utf-8?q?Arsen_Arsenovi=C4=87?= , Iain Sandoe Subject: [PATCH] warn-access: ignore template parameters when matching operator new/delete [PR109224] Date: Fri, 2 Aug 2024 22:36:57 +0200 Message-ID: <20240802211503.3992610-2-arsen@aarsen.me> MIME-Version: 1.0 X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_INFOUSMEBIZ, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org I'm not 100% clear on what the semantics of the matching here are meant to be - AFAICT, an operator new/delete pair matches (after falling through the other cases) if all their components (besides the actual operator name, of course) match, and the pair of actual operator names matches if one is a singleton new and the other a singleton delete, or, similarly, if one is an array new and the other an array delete. We also appear to ignore their argument types (or so it seems by experimentation - I was not able to quite discern what path those take). Stripping operator template arguments from either side of the pair should have no impact on this logic, I think. Tested on x86_64-pc-linux-gnu, no regressions. OK for trunk? TIA, have a lovely evening. ---------- >8 ---------- Template parameters on a member operator new cannot affect its member status nor whether it is a singleton or array operator new, hence, we can ignore it for purposes of matching. Similar logic applies to the placement operator delete. In the PR (and a lot of idiomatic coroutine code generally), operator new is templated in order to be able to inspect (some of) the arguments passed to the coroutine, to make allocation-related decisions. However, the coroutine implementation will not call a placement delete form, so it cannot get templated. As a result, when demangling, we have an extra template DEMANGLE_COMPONENT_TEMPLATE around the actual operator new, but not operator delete. This terminates new_delete_mismatch_p early. PR middle-end/109224 - Wmismatched-new-delete false positive with a templated operator new (common with coroutines) gcc/ChangeLog: PR middle-end/109224 * gimple-ssa-warn-access.cc (new_delete_mismatch_p): Strip DEMANGLE_COMPONENT_TEMPLATE from the operator new and operator after demangling. gcc/testsuite/ChangeLog: PR middle-end/109224 * g++.dg/warn/Wmismatched-new-delete-9.C: New test. --- gcc/gimple-ssa-warn-access.cc | 18 ++++++- .../g++.dg/warn/Wmismatched-new-delete-9.C | 47 +++++++++++++++++++ gcc/testsuite/g++.dg/warn/pr109224.C | 25 ++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-9.C create mode 100644 gcc/testsuite/g++.dg/warn/pr109224.C diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 61f9f0f3d310..e3fec5fb8e77 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -1762,7 +1762,23 @@ new_delete_mismatch_p (tree new_decl, tree delete_decl) void *np = NULL, *dp = NULL; demangle_component *ndc = cplus_demangle_v3_components (new_str, 0, &np); demangle_component *ddc = cplus_demangle_v3_components (del_str, 0, &dp); - bool mismatch = ndc && ddc && new_delete_mismatch_p (*ndc, *ddc); + + /* Sometimes, notably quite often with coroutines, 'operator new' is + templated. However, template arguments can't change whether a given + new/delete is a singleton or array one, nor what it is a member of, so + the template arguments can be safely ignored for the purposes of checking + for mismatches. */ + + auto strip_dc_template = [] (demangle_component* dc) + { + if (dc->type == DEMANGLE_COMPONENT_TEMPLATE) + dc = dc->u.s_binary.left; + return dc; + }; + + bool mismatch = ndc && ddc + && new_delete_mismatch_p (*strip_dc_template (ndc), + *strip_dc_template (ddc)); free (np); free (dp); return mismatch; diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-9.C b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-9.C new file mode 100644 index 000000000000..fa511bbfdb4b --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-9.C @@ -0,0 +1,47 @@ +/* { dg-do compile { target c++11 } } */ +/* { dg-additional-options "-Wmismatched-new-delete" } */ +/* PR middle-end/109224 */ +/* Verify that we consider templated operator new matching with its operator + delete. */ + +#include + +struct foo +{ + template + void* operator new (std::size_t sz, Args&&...); + template + void* operator new[] (std::size_t sz, Args&&...); + + void operator delete (void* x); + void operator delete[] (void* x); + + template + void operator delete (void* x, Args&&...); + template + void operator delete[] (void* x, Args&&...); +}; + +void +f () +{ + delete (new (123, true) foo); + delete[] (new (123, true) foo[123]); + + delete (new (123, true) foo[123]); + // { dg-warning "Wmismatched-new-delete" "" { target *-*-* } {.-1} } + // { dg-note "returned from" "" { target *-*-* } {.-2} } + delete[] (new (123, true) foo); + // { dg-warning "Wmismatched-new-delete" "" { target *-*-* } {.-1} } + // { dg-note "returned from" "" { target *-*-* } {.-2} } + + foo::operator delete (new (123, true) foo, 123, true); + foo::operator delete[] (new (123, true) foo[123], 123, true); + + foo::operator delete (new (123, true) foo[123], 123, true); + // { dg-warning "Wmismatched-new-delete" "" { target *-*-* } {.-1} } + // { dg-note "returned from" "" { target *-*-* } {.-2} } + foo::operator delete[] (new (123, true) foo, 123, true); + // { dg-warning "Wmismatched-new-delete" "" { target *-*-* } {.-1} } + // { dg-note "returned from" "" { target *-*-* } {.-2} } +} diff --git a/gcc/testsuite/g++.dg/warn/pr109224.C b/gcc/testsuite/g++.dg/warn/pr109224.C new file mode 100644 index 000000000000..4b6102226ffc --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/pr109224.C @@ -0,0 +1,25 @@ +// { dg-do compile { target c++20 } } +#include + +struct Task { + struct promise_type { + std::suspend_never initial_suspend() { return {}; } + std::suspend_never final_suspend() noexcept { return {}; } + void unhandled_exception() { throw; } + Task get_return_object() { return {}; } + void return_void() {} + + template + void* operator new(std::size_t sz, I); + + void operator delete(void* ptr, std::size_t); + }; +}; + +Task f(int) { + co_return; +} + +int main() { + f(42); +}