[Bug middle-end/103993] -Wismatched-new-delete due to difference in inlining decisions
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103993 cdfrey at foursquare dot net changed: What|Removed |Added CC||cdfrey at foursquare dot net --- Comment #5 from cdfrey at foursquare dot net --- This happens for me. Here is a test case, for gcc 13.1.0, which gives the warning with this command: /home/gcc/rootdir/gcc-13.1.0/bin/g++ -Wall -O2 --std=c++17 -Wall -Wextra -Werror -fmax-errors=4 -c -o gcc-test-case.o gcc-test-case.cc gcc-test-case.cc: In function ‘int main()’: gcc-test-case.cc:49:16: error: ‘static void Test::operator delete(void*)’ called on pointer returned from a mismatched allocation function [-Werror=mismatched-new-delete] 49 | delete t; |^ In static member function ‘static void* Test::operator new(size_t)’, inlined from ‘int main()’ at gcc-test-case.cc:48:10: gcc-test-case.cc:17:30: note: returned from ‘void* malloc(size_t)’ 17 | return malloc(size); |~~^~ gcc-test-case.cc: In function ‘int main()’: gcc-test-case.cc:48:17: error: ‘static void Test::operator delete(void*)’ called on pointer returned from a mismatched allocation function [-Werror=mismatched-new-delete] 48 | t = new Test; | ^~~~ In static member function ‘static void* Test::operator new(size_t)’, inlined from ‘int main()’ at gcc-test-case.cc:48:10: gcc-test-case.cc:17:30: note: returned from ‘void* malloc(size_t)’ 17 | return malloc(size); |~~^~ cc1plus: all warnings being treated as errors make: *** [: gcc-test-case.o] Error 1 The code: #include // cout statements needed to trigger warning #include #include using namespace std; struct Test { double a, b, c; Test() { cout << "Test::Test()\n"; } void* operator new(size_t size) { cout << "Test::operator new(" << size << ")\n"; return malloc(size); } void* operator new(size_t size, align_val_t al) { cout << "Test::operator new(" << size << ", align: " << (size_t)al << ")\n"; return aligned_alloc((size_t)al, size); } void* operator new(size_t size, const std::nothrow_t &) throw() { cout << "Test::operator new(" << size << ", nothrow)\n"; return malloc(size); } void operator delete(void *p) { cout << "Test::operator delete()\n"; free(p); } void operator delete(void *p, align_val_t al) { cout << "Test::operator delete(p, align: " << (size_t)al << ")\n"; free(p); } }; int main(void) { Test *t; t = new Test; delete t; }
[Bug middle-end/103993] -Wismatched-new-delete due to difference in inlining decisions
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103993 --- Comment #4 from Ed Catmur --- And another example, provoked by throwing new (this only happens at -Og): #include struct D { D(); static void* operator new (std::size_t s) { if (void* p = ::malloc(s)) return p; throw "bad_alloc"; } static void operator delete (void* p) { ::free(p); } }; int main() { new D; }
[Bug middle-end/103993] -Wismatched-new-delete due to difference in inlining decisions
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103993 andre at kostur dot net changed: What|Removed |Added CC||andre at kostur dot net --- Comment #3 from andre at kostur dot net --- Here's a smaller, minimal example of the issue (as described in the subject): #include struct Foo { static void * operator new( size_t s ) __attribute__( ( noinline ) ) { return ::operator new( s ); } static void operator delete( void * p ) { return ::operator delete( p ); } }; int main() { Foo * f = new Foo(); delete f; }
[Bug middle-end/103993] -Wismatched-new-delete due to difference in inlining decisions
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103993 Martin Sebor changed: What|Removed |Added Blocks||100406 CC||msebor at gcc dot gnu.org See Also||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=100861 Summary|Incorrect error generated |-Wismatched-new-delete due |by mismatched-new-delete|to difference in inlining ||decisions Keywords||diagnostic Component|c++ |middle-end --- Comment #2 from Martin Sebor --- The reported mismatch is between void operator delete [](void*) and void* ACE_Svc_Handler::operator new(size_t) i.e., the array form of the global operator delete is being called on the result of a scalar member operator new. The deallocation function corresponding to a member array new is a member array delete, so the warning isn't incorrect per se. The warning is based on the compiler's view of the optimized code, after inlining and other transformations. If the program provides overloads of operators new and delete for some type and GCC inlines a call to one but not the other, the warning will trigger because it sees a mismatch. To avoid this problem either prevent the inlining of both the allocation and the deallocation function (using attribute noinline), or force both to be inlined (by declaring them inline and attribute always_inline). The diff below shows the latter solution. It's possible for GCC do the former automatically (and it does that for a subset of these cases) but given it's not without a performance cost it seems preferable to leave the choice up to the programmer. Another approach was suggested in pr101829. See also pr100861 for a discussions of another similar issue. (When reporting a problem it's helpful to explain why you think it's in GCC rather than in the submitted test case so we don't have to guess.) $ diff -u JSimpleProcess.C JSimpleProcess-fix.C --- JSimpleProcess.C2022-01-12 11:06:52.787461649 -0700 +++ JSimpleProcess-fix.C2022-01-12 11:18:30.085356124 -0700 @@ -78365,7 +78365,8 @@ ; return; } -template void * +template +inline __attribute__ ((always_inline)) void * ACE_Svc_Handler::operator new (size_t n) { ; @@ -78378,10 +78379,11 @@ else { dynamic_instance->set (); - return ::new char[n]; + return ::operator new (n); } } -template void * +template +inline __attribute__ ((always_inline)) void * ACE_Svc_Handler::operator new (size_t n, const ::std::nothrow_t&) throw() { @@ -78395,15 +78397,16 @@ else { dynamic_instance->set (); - return ::new(::std::nothrow) char[n]; + return ::operator new(n, ::std::nothrow); } } -template void +template +inline __attribute__ ((always_inline)) void ACE_Svc_Handler::operator delete (void *p, const ::std::nothrow_t&) throw() { ; - ::delete [] static_cast (p); + ::operator delete (p); } template void ACE_Svc_Handler::destroy () @@ -78412,11 +78415,12 @@ if (this->mod_ == 0 && this->dynamic_ && this->closing_ == false) delete this; } -template void +template +inline __attribute__ ((always_inline)) void ACE_Svc_Handler::operator delete (void *obj) { ; - ::delete [] static_cast (obj); + ::operator delete (obj); } template ACE_Svc_Handler::ACE_Svc_Handler (ACE_Thread_Manager *tm, Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100406 [Bug 100406] bogus/missing -Wmismatched-new-delete