Bug 107694 - Bogus stringop-overflow warning in gcc 12
Summary: Bogus stringop-overflow warning in gcc 12
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 12.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Keywords: diagnostic
Depends on:
Blocks: Wstringop-overflow
  Show dependency treegraph
Reported: 2022-11-15 09:08 UTC by Mike Hommey
Modified: 2023-05-19 04:37 UTC (History)
2 users (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed:


Note You need to log in before you can comment on or make changes to this bug.
Description Mike Hommey 2022-11-15 09:08:31 UTC
#include <atomic>

class nsISupports {
  virtual int Release();
struct JSPrincipals {
  std::atomic<int> refcount;
class nsJSPrincipals : nsISupports, JSPrincipals {
  static nsJSPrincipals* get(JSPrincipals* principals) {
    return static_cast<nsJSPrincipals*>(principals);
  void Destroy(JSPrincipals* jsprin);

void nsJSPrincipals::Destroy(JSPrincipals* jsprin) {
 nsJSPrincipals* nsjsprin = nsJSPrincipals::get(jsprin);
 nsjsprin->refcount.fetch_add(1, std::memory_order_acq_rel);

Compile with: g++ -c -O2 -Werror=stringop-overflow

It says:
In file included from /builds/worker/fetches/gcc/include/c++/12.2.0/atomic:41,
                 from Unified_cpp_caps0.ii.cpp:1:
In member function 'std::__atomic_base<_IntTp>::__int_type std::__atomic_base<_IntTp>::fetch_add(__int_type, std::memory_order) [with _ITp = int]',
    inlined from 'void nsJSPrincipals::Destroy(JSPrincipals*)' at Unified_cpp_caps0.ii.cpp:19:30:
/builds/worker/fetches/gcc/include/c++/12.2.0/bits/atomic_base.h:618:34: error: 'unsigned int __atomic_fetch_add_4(volatile void*, unsigned int, int)' writing 4 bytes into a region of size 0 overflows the destination [-Werror=stringop-overflow=]
  618 |       { return __atomic_fetch_add(&_M_i, __i, int(__m)); }
      |                ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
cc1plus: some warnings being treated as errors
Comment 1 Andrew Pinski 2023-05-19 04:37:50 UTC
PR 109571 is basically the same here just with a different warning (and upcasting instead of downcasting).

In this case if we look at:
void nsJSPrincipals::Destroy(JSPrincipals* jsprin) {
 nsJSPrincipals* nsjsprin = nsJSPrincipals::get(jsprin);

if jsprin is null, then nsjsprin needs to be null too. And since nsjsprin == jsprin-8(bytes) (if it was a valid pointer), the C++ front-end needs to add a check for null. And then the optimizations come along and does jump threading.
so one way of removing this is adding an assumption which can be done via one of the following:
  if (!jsprin) __builtin_unreachable();

The first one is valid for GCC all the way back in 4.7 (and before).
the second one is C++23 and was only added in GCC 13.