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

            Bug ID: 125913
           Summary: [16/17 regression] False positive
                    -Wfree-nonheap-object
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: aleksandr9809 at gmail dot com
  Target Milestone: ---

Hi,

While migrating private codebase to the GCC 16, I faced with the possibly
false-positive bug.

The minimized code with the our problem:

```cxx
// g++ -std=c++17 -O2 -Wall -Werror -c file.cpp

#include <atomic>

struct Interface {
    virtual ~Interface() = default;
    virtual void Release() = 0;
};

// Core of Implementation: delete this + ~dtor calls helper->Release()
struct Implementation : virtual Interface {
    struct Helper {
        int selfRc = 1;
        std::atomic<int> ownerRc{1};
        void Release() { if (--selfRc == 0) delete this; }
    };
    Helper* helper;
    Implementation() : helper(new Helper) {}
    virtual ~Implementation() { helper->Release(); }
    void Release() override {
        if (helper->ownerRc.fetch_sub(1) == 1)
            delete this;
    }
};

template<class T>
struct RAII {
    T* p;
    explicit RAII(T* p) : p(p) {}
    virtual ~RAII() { p->Release(); }
};

struct OtherBase { virtual ~OtherBase() = default; };

// virtual MI => Implementation is at a non-zero offset from new()
struct Object final : virtual OtherBase, virtual Implementation {};

int main() {
    RAII<Object> obj(new Object);
}
```

The compiler generates the next error message:
```
In destructor 'virtual Implementation::~Implementation()',
    inlined from 'virtual void Implementation::Release()' at <source>:22:20,
    inlined from 'virtual void Implementation::Release()' at <source>:20:10,
    inlined from 'RAII<T>::~RAII() [with T = Object]' at <source>:30:33,
    inlined from 'int main()' at <source>:40:1:
<source>:19:52: error: 'void operator delete(void*)' called on pointer
'<unknown>' with nonzero offset 8 [-Werror=free-nonheap-object]
   19 |     virtual ~Implementation() { helper->Release(); }
      |                                                    ^
<source>: In function 'int main()':
<source>:39:26: note: returned from 'void* operator new(std::size_t)'
   39 |     RAII<Object> obj(new Object);
      |                          ^~~~~~
```

The godbolt link with proof: https://www.godbolt.org/z/cG5xzGKc1

The issue is reproduced in both gcc trunk and gcc 16.1, but not on gcc 15.2
(Godbolt-provided) or earlier GCC versions (Debian-provided GCC 8.3.0, 10.2.1,
12.2.0, 14.2.0).

Maybe it's the C++ standard misunderstanding, but there's no triggers from ASan
or UBSan from the gcc 16.1.0 (godbolt-provided).

Best regards,
Alex
  • [Bug c++/125913] New: [16/17 r... aleksandr9809 at gmail dot com via Gcc-bugs

Reply via email to