Bug 105585

Summary: [12/13 Regression] Spurious stringop-overflow warning with <atomic> since r12-4725-g88b504b7a8c5affb
Product: gcc Reporter: Ed Catmur <ed>
Component: tree-optimizationAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED INVALID    
Severity: normal CC: marxin, msebor
Priority: P3 Keywords: diagnostic
Version: 12.1.0   
Target Milestone: 12.2   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2022-05-13 00:00:00
Bug Depends on:    
Bug Blocks: 88443    

Description Ed Catmur 2022-05-12 16:58:07 UTC
Reduced (from code in abseil-cpp):

#include <atomic>
struct S {
  int i;
  std::atomic<int> a;
};
S* q();
void f();
void g(bool b) {
  auto p = b ? q() : nullptr;
  ++p->a;
  if (p)
    f();
}

In file included from atomic:41,
                 from <source>:1:
In member function 'std::__atomic_base<_IntTp>::__int_type std::__atomic_base<_IntTp>::operator++() [with _ITp = int]',
    inlined from 'void g(bool)' at <source>:10:3:
bits/atomic_base.h:385:34: warning: 'unsigned int __atomic_add_fetch_4(volatile void*, unsigned int, int)' writing 4 bytes into a region of size 0 overflows the destination [-Wstringop-overflow=]
  385 |       { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); }
      |                ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comment 1 Ed Catmur 2022-05-12 16:59:57 UTC
Flags: -O1 -Wstringop-overflow=1
https://godbolt.org/z/8r8roz7Pa
Comment 2 Ed Catmur 2022-05-12 17:50:32 UTC
Affected code: https://github.com/abseil/abseil-cpp/issues/1175
The proposed patch to abseil-cpp corresponds to adding an assumption that `b` is true above.
Comment 3 Martin Liška 2022-05-13 12:02:19 UTC
Started with r12-4725-g88b504b7a8c5affb.
Comment 4 Martin Sebor 2022-05-17 14:15:30 UTC
The warning is caused by the if statement: if p is null, accessing the p->a member is undefined.  It triggers because the GCC optimizer splits the code into two branches: one with a nonnull p and another with a null p.  The second one triggers the warning.

If p can be null then moving the increment to the body of the if statement avoids the undefined behavior (and the warning).  If p cannot be null then making the if statement unconditional also avoids the warning.