Hi, Arsen Arsenović <[email protected]> writes:
>> The && should not be left of the =; if the initializer needs to span multiple
>> lines, it's usually best to wrap it in ().
>
> Okay - done.
[...]
>>> + foo::operator delete (new (123, true) foo, 123, true);
>>> + foo::operator delete[] (new (123, true) foo[123], 123, true);
>>
>> Instead of passing the result of a new-expression directly to operator
>> delete,
>> you should also call operator new directly.
>>
>>> + 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);
>>
>> Likewise.
>
> Ah, good point - adjusted.
>
> Here are the changes to v1 I've made as well as the full patch below
> them. Does this look OK?
>
> --8<---------------cut here---------------start------------->8---
> modified gcc/gimple-ssa-warn-access.cc
> @@ -1776,9 +1776,9 @@ new_delete_mismatch_p (tree new_decl, tree delete_decl)
> return dc;
> };
>
> - bool mismatch = ndc && ddc
> - && new_delete_mismatch_p (*strip_dc_template (ndc),
> - *strip_dc_template (ddc));
> + bool mismatch = (ndc && ddc
> + && new_delete_mismatch_p (*strip_dc_template (ndc),
> + *strip_dc_template (ddc)));
> free (np);
> free (dp);
> return mismatch;
> modified gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-9.C
> @@ -35,13 +35,13 @@ f ()
> // { 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 (foo::operator new (1, 123, true), 123, true);
> + foo::operator delete[] (foo::operator new[] (123, 123, true), 123, true);
>
> - foo::operator delete (new (123, true) foo[123], 123, true);
> + foo::operator delete (foo::operator new[] (123, 123, true), 123, true);
> // { 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[] (foo::operator new (1, 123, true), 123, true);
> // { dg-warning "Wmismatched-new-delete" "" { target *-*-* } {.-1} }
> // { dg-note "returned from" "" { target *-*-* } {.-2} }
> }
> --8<---------------cut here---------------end--------------->8---
Gentle ping on this adjustment to the patch (full reproduction of the
adjusted patch is below).
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:
>
> * gimple-ssa-warn-access.cc (new_delete_mismatch_p): Strip
> DEMANGLE_COMPONENT_TEMPLATE from the operator new and operator
> after demangling.
>
> gcc/testsuite/ChangeLog:
>
> * 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..fcce63ee332d 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..d431f4049e87
> --- /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 <new>
> +
> +struct foo
> +{
> + template<typename... Args>
> + void* operator new (std::size_t sz, Args&&...);
> + template<typename... Args>
> + void* operator new[] (std::size_t sz, Args&&...);
> +
> + void operator delete (void* x);
> + void operator delete[] (void* x);
> +
> + template<typename... Args>
> + void operator delete (void* x, Args&&...);
> + template<typename... Args>
> + 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 (foo::operator new (1, 123, true), 123, true);
> + foo::operator delete[] (foo::operator new[] (123, 123, true), 123, true);
> +
> + foo::operator delete (foo::operator new[] (123, 123, true), 123, true);
> + // { dg-warning "Wmismatched-new-delete" "" { target *-*-* } {.-1} }
> + // { dg-note "returned from" "" { target *-*-* } {.-2} }
> + foo::operator delete[] (foo::operator new (1, 123, true), 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 <coroutine>
> +
> +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<class I>
> + 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);
> +}
--
Arsen Arsenović
signature.asc
Description: PGP signature
