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;
}

Reply via email to