public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/100861] New: False positive -Wmismatched-new-delete with destroying operator delete
@ 2021-06-01 19:43 josephcsible at gmail dot com
  2021-06-01 21:36 ` [Bug middle-end/100861] " msebor at gcc dot gnu.org
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: josephcsible at gmail dot com @ 2021-06-01 19:43 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100861

            Bug ID: 100861
           Summary: False positive -Wmismatched-new-delete with destroying
                    operator delete
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Keywords: diagnostic
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: josephcsible at gmail dot com
  Target Milestone: ---

Currently, code like "Base *b = new Derived; delete b;" gives a
-Wmismatched-new-delete warning, unless Base has a virtual destructor. One of
the use cases for C++20's destroying operator delete is to make this safe
without needing a virtual destructor, so this warning should be suppressed if
Base has a destroying operator delete. Here's a modified version of the code at
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0722r1.html that will
unnecessarily cause this warning (compile with -std=c++20 -Wall):

#include <new>

enum class WidgetKind {
  Grommet,
  Wingnut
};

struct Widget {
  const WidgetKind Kind : 4;
  unsigned OtherThings : 28;

  Widget(WidgetKind k) : Kind(k) {}
  void operator delete(Widget *, std::destroying_delete_t);
};

struct Grommet : Widget {
  Grommet() : Widget(WidgetKind::Grommet) {}
};

struct Wingnut : Widget {
  Wingnut() : Widget(WidgetKind::Wingnut) {}
};

void Widget::operator delete(Widget *widget, std::destroying_delete_t) {
  switch (widget->Kind) {
  case WidgetKind::Grommet:
    static_cast<Grommet*>(widget)->~Grommet();
    ::operator delete(widget, sizeof(Grommet));
    return;
  case WidgetKind::Wingnut:
    static_cast<Wingnut*>(widget)->~Wingnut();
    ::operator delete(widget, sizeof(Wingnut));
    return;
  }
}

int main() {
  Widget *widget = new Grommet;
  delete widget;
}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/100861] False positive -Wmismatched-new-delete with destroying operator delete
  2021-06-01 19:43 [Bug c++/100861] New: False positive -Wmismatched-new-delete with destroying operator delete josephcsible at gmail dot com
@ 2021-06-01 21:36 ` msebor at gcc dot gnu.org
  2021-06-01 21:49 ` josephcsible at gmail dot com
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-06-01 21:36 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100861

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |enhancement
             Status|UNCONFIRMED                 |NEW
          Component|c++                         |middle-end
   Last reconfirmed|                            |2021-06-01
                 CC|                            |msebor at gcc dot gnu.org
     Ever confirmed|0                           |1
             Blocks|                            |100406

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning doesn't do anything special with destroying operator delete or any
other kinds of the operators (other than scalar vs array).  It triggers for
this test case because it sees the result of ::operator new() being passed to
Widget::operator delete (Widget*).  If Widget::operator delete() is inlined
(e.g., declared with attribute always_inline) the warning goes away just as
long as the operator doesn't pass the pointer to the wrong overload of delete. 
Alternatively, if Widget defines a non-inline member operator new() that also
prevents the warning because calls to both operators match.

With that, I'm not sure that suppressing the warning for a destroying operator
delete() would be a good solution.  It seems to me that the right fix is to
solve the broader problem where one of the operators is inlined and the other
isn't (similar to pr100485, except with the definitions of both operators
available in the same translation unit).

Until/unless a solution is developed I would suggest to either define the
destroying operator delete inline and have it call an out-of-line function to
do the work (as shown below) or to force the inlining of the destroying delete.

struct Widget {
  const WidgetKind Kind : 4;
  unsigned OtherThings : 28;

  Widget(WidgetKind k) : Kind(k) {}

  void operator delete(Widget *widget, std::destroying_delete_t) {
    destroy_delete (widget);
  }

  static __attribute__ ((noinline)) void destroy_delete (Widget *);
};


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100406
[Bug 100406] bogus/missing -Wmismatched-new-delete

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/100861] False positive -Wmismatched-new-delete with destroying operator delete
  2021-06-01 19:43 [Bug c++/100861] New: False positive -Wmismatched-new-delete with destroying operator delete josephcsible at gmail dot com
  2021-06-01 21:36 ` [Bug middle-end/100861] " msebor at gcc dot gnu.org
@ 2021-06-01 21:49 ` josephcsible at gmail dot com
  2021-06-01 22:08 ` msebor at gcc dot gnu.org
  2023-12-22 18:31 ` pinskia at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: josephcsible at gmail dot com @ 2021-06-01 21:49 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100861

--- Comment #2 from Joseph C. Sible <josephcsible at gmail dot com> ---
Wait, if it's just checking whether the calls to operator new and operator
delete match up, then why does adding "virtual ~Widget() {}" make the warning
go away?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/100861] False positive -Wmismatched-new-delete with destroying operator delete
  2021-06-01 19:43 [Bug c++/100861] New: False positive -Wmismatched-new-delete with destroying operator delete josephcsible at gmail dot com
  2021-06-01 21:36 ` [Bug middle-end/100861] " msebor at gcc dot gnu.org
  2021-06-01 21:49 ` josephcsible at gmail dot com
@ 2021-06-01 22:08 ` msebor at gcc dot gnu.org
  2023-12-22 18:31 ` pinskia at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-06-01 22:08 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100861

--- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> ---
The virtual dtor forces an out-of-line call to the Grommet dtor which then
calls ::operator delete(), so the warning has nothing to complain about.  It
sees this code (compile with -fdump-tree-optimized=/dev/stdout):

int main ()
{
  void * _3;

  <bb 2> [local count: 1073741824]:
  _3 = operator new (16);
  MEM[(struct Widget *)_3].Kind = 0;
  MEM[(struct Grommet *)_3].D.2504._vptr.Widget = &MEM <int (*) ()[4]> [(void
*)&_ZTV7Grommet + 16B];
  Grommet::~Grommet (_3);
  return 0;

}

whereas with the original test case it sees:

int main ()
{
  struct destroying_delete_t D.2584;
  void * _3;

  <bb 2> [local count: 1073741824]:
  _3 = operator new (4);
  Widget::operator delete (_3, D.2584);   <<< warning here
  return 0;

}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/100861] False positive -Wmismatched-new-delete with destroying operator delete
  2021-06-01 19:43 [Bug c++/100861] New: False positive -Wmismatched-new-delete with destroying operator delete josephcsible at gmail dot com
                   ` (2 preceding siblings ...)
  2021-06-01 22:08 ` msebor at gcc dot gnu.org
@ 2023-12-22 18:31 ` pinskia at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-12-22 18:31 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100861

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |fchelnokov at gmail dot com

--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
*** Bug 113113 has been marked as a duplicate of this bug. ***

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-12-22 18:31 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-01 19:43 [Bug c++/100861] New: False positive -Wmismatched-new-delete with destroying operator delete josephcsible at gmail dot com
2021-06-01 21:36 ` [Bug middle-end/100861] " msebor at gcc dot gnu.org
2021-06-01 21:49 ` josephcsible at gmail dot com
2021-06-01 22:08 ` msebor at gcc dot gnu.org
2023-12-22 18:31 ` pinskia at gcc dot gnu.org

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).