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

            Bug ID: 117204
           Summary: [12/13/14/15 regression] After r12-2132-ga1108556677,
                    bogus -Warray-bounds warnings in std::vector::back()
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dimi...@unified-streaming.com
  Target Milestone: ---

We noticed spurious -Warray-bounds warnings in some C++20 code compiled with
g++ 13, and I bisected it to commit r12-2132-ga1108556677 ("Correct handling of
variable offset minus constant in -Warray-bounds [PR100137]"), also meant to
resolve bug 97027, bug 99121 and bug 100137.

Minimized test case:

----------------------------------------------------------------------
// g++ -std=c++20 -Wall -O2 -c splice-min.cpp
template <typename> struct allocator;
template <typename> struct allocator_traits;
template <typename _Tp> struct allocator_traits<allocator<_Tp>> {
  using value_type = _Tp;
  using pointer = _Tp *;
  template <typename _Up> using rebind_alloc = allocator<_Up>;
};
template <typename _Alloc> struct __alloc_traits : allocator_traits<_Alloc> {
  typedef allocator_traits<_Alloc> _Base_type;
  typedef _Base_type::value_type reference;
  template <typename _Tp> struct rebind {
    typedef _Base_type::template rebind_alloc<_Tp> other;
  };
};
int nullopt, timescale_, add_chunk_duration = timescale_, __trans_tmp_1,
                         chunker_next_media_segment;
struct optional {
  template <typename _Up> optional(_Up);
  operator bool();
};
template <typename _Tp, typename _Alloc> struct _Vector_base {
  typedef __alloc_traits<_Alloc>::template rebind<_Tp>::other _Tp_alloc_type;
  typedef __alloc_traits<_Tp_alloc_type>::pointer pointer;
  struct {
    pointer _M_finish;
  } _M_impl;
};
template <typename _Tp, typename _Alloc = allocator<_Tp>>
struct vector : _Vector_base<_Tp, _Alloc> {
  typedef _Vector_base<_Tp, _Alloc> _Base;
  typedef _Base::pointer iterator;
  using _Base::_M_impl;
  vector();
  vector(vector &) { _M_impl._M_finish = 0; }
  __alloc_traits<typename _Base::_Tp_alloc_type>::reference back() {
    iterator __trans_tmp_5 = _M_impl._M_finish, __trans_tmp_2 = __trans_tmp_5;
    return *(__trans_tmp_2 - 1);
  }
};
struct timespan_t {
  unsigned get_end();
};
enum gap_t {};
struct tdr_t {
  void end_time();
  long time_;
  long duration_;
  gap_t gap_;
};
struct fragment_timeline_t {
  void append(long, long) {
    tdr_t last = times_.back();
    last.end_time();
  }
  vector<tdr_t> times_;
};
vector<fragment_timeline_t> timelines_;
struct chunk_t {
  long time_;
} __trans_tmp_3, chunker_chunk = __trans_tmp_3;
struct collector_t {
  collector_t(long);
  bool add_chunk(chunk_t chunk) {
    fragment_timeline_t __trans_tmp_4;
    auto time = chunk.time_;
    __trans_tmp_4 = timelines_.back();
    __trans_tmp_4.append(time, add_chunk_duration);
    return true;
  }
};
struct unpack_t {
  unpack_t(int);
  optional operator()();
};
timespan_t chunker_timespan;
unsigned int chunker_end = chunker_timespan.get_end();
int chunker() {
  unpack_t unpack(chunker_next_media_segment), opt_curr = unpack;
  collector_t collector(0);
  auto opt_next = unpack();
  auto get_chunk = [&]() -> optional {
    if (opt_next) {
      auto chunk = opt_curr;
      return chunk;
    }
    return nullopt;
  };
  while (get_chunk()) {
    if (chunker_end)
      collector.add_chunk(chunker_chunk);
  }
  return __trans_tmp_1;
}
----------------------------------------------------------------------

$ ~/ins/gcc-12-2131-g6278065af07/bin/g++ -std=c++20 -Wall -O2 -c splice-min.cpp
<silent>

$ ~/ins/gcc-12-2132-ga1108556677/bin/g++ -std=c++20 -Wall -O2 -c splice-min.cpp
In member function 'typename __alloc_traits<typename _Vector_base<_Tp,
_Alloc>::_Tp_alloc_type>::reference vector<_Tp, _Alloc>::back() [with _Tp =
tdr_t; _Alloc = allocator<tdr_t>]',
    inlined from 'void fragment_timeline_t::append(long int, long int)' at
splice-min.cpp:53:29,
    inlined from 'bool collector_t::add_chunk(chunk_t)' at
splice-min.cpp:68:25,
    inlined from 'int chunker()' at splice-min.cpp:91:26:
splice-min.cpp:38:31: warning: array subscript -1 is outside array bounds of
'tdr_t [384307168202282325]' [-Warray-bounds]
   38 |     return *(__trans_tmp_2 - 1);
      |                               ^

Especially the value 384307168202282325, which corresponds to
0x555555555555555, is suspect. I am guessing that gcc is accessing some
uninitialized memory here, which was pre-filled with 0x55 bytes by the
allocator?

Reply via email to