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

            Bug ID: 127140
           Summary: analyzer reports false positives with
                    std::unordered_map
           Product: gcc
           Version: 15.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: analyzer
          Assignee: dmalcolm at gcc dot gnu.org
          Reporter: sudolskym at gmail dot com
  Target Milestone: ---

Target: x86_64-pc-linux-gnu (Ubuntu 24.04.4 LTS)
Configured with: ../gcc-15-source/configure --prefix=/opt/gcc-15
--disable-multilib --enable-languages=c++
gcc version 15.2.0 (GCC)

Page https://gcc.gnu.org/bugs/ says to post preprocessed file (*.i*) instead of
source but that has 1 MB while original source is minimalistic, self-contained
and short:

#include <unordered_map>
int main()
{
    std::unordered_map<int, int> x;
    x[10] = 10;
}

g++ -std=c++26 -Wall -Wextra -Wpedantic -fanalyzer a.cpp



In file included from
/opt/gcc-15/include/c++/15.2.0/x86_64-pc-linux-gnu/bits/c++allocator.h:33,
                 from /opt/gcc-15/include/c++/15.2.0/bits/allocator.h:46,
                 from /opt/gcc-15/include/c++/15.2.0/bits/alloc_traits.h:39,
                 from /opt/gcc-15/include/c++/15.2.0/ext/alloc_traits.h:36,
                 from
/opt/gcc-15/include/c++/15.2.0/bits/hashtable_policy.h:39,
                 from /opt/gcc-15/include/c++/15.2.0/bits/hashtable.h:37,
                 from /opt/gcc-15/include/c++/15.2.0/bits/unordered_map.h:33,
                 from /opt/gcc-15/include/c++/15.2.0/unordered_map:43,
                 from a.cpp:3:
In member function ‘constexpr std::__new_allocator<_Tp>::size_type
std::__new_allocator<_Tp>::_M_max_size() const [with _Tp =
std::__detail::_Hash_node<std::pair<const int, int>, false>]’,
    inlined from ‘_Tp* std::__new_allocator<_Tp>::allocate(size_type, const
void*) [with _Tp = std::__detail::_Hash_node<std::pair<const int, int>,
false>]’ at /opt/gcc-15/include/c++/15.2.0/bits/new_allocator.h:134:46:
/opt/gcc-15/include/c++/15.2.0/bits/new_allocator.h:233:57: warning: leak of
‘__a->std::__new_allocator<std::__detail::_Hash_node<std::pair<const int, int>,
false> >::allocate(__n, 0)’ [CWE-401] [-Wanalyzer-malloc-leak]
  233 |         return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
      |                                                         ^
  ‘std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type*
std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...)
[with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>,
std::tuple<>}; _NodeAlloc =
std::allocator<std::__detail::_Hash_node<std::pair<const int, int>, false> >]’:
events 1-2
    │
    │/opt/gcc-15/include/c++/15.2.0/bits/hashtable_policy.h:1547:7:
    │ 1547 |       _Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&&...
__args)
    │      |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    │      |       |
    │      |       (1) entry to
‘std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const
int, int>, false> > >::_M_allocate_node<const std::piecewise_construct_t&,
std::tuple<int&&>, std::tuple<> >’
    │......
    │ 1551 |         auto __nptr = __node_alloc_traits::allocate(__alloc, 1);
    │      |                                                    ~
    │      |                                                    |
    │      |                                                    (2) inlined
call to
‘std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<const
int, int>, false> > >::allocate’ from
‘std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const
int, int>, false> > >::_M_allocate_node<const std::piecewise_construct_t&,
std::tuple<int&&>, std::tuple<> >’
    │
    └──> ‘static constexpr _Tp* std::allocator_traits<std::allocator<_Up>
>::allocate(allocator_type&, size_type) [with _Tp =
std::__detail::_Hash_node<std::pair<const int, int>, false>]’: event 3
           │
           │/opt/gcc-15/include/c++/15.2.0/bits/alloc_traits.h:614:28:
           │  614 |       { return __a.allocate(__n); }
           │      |                            ^
           │      |                            |
           │      |                            (3) inlined call to
‘std::allocator<std::__detail::_Hash_node<std::pair<const int, int>, false>
>::allocate’ from
‘std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<const
int, int>, false> > >::allocate’
           │
           └──> ‘constexpr _Tp* std::allocator< <template-parameter-1-1>
>::allocate(std::size_t) [with _Tp = std::__detail::_Hash_node<std::pair<const
int, int>, false>]’: events 4-5
                  │
                  │/opt/gcc-15/include/c++/15.2.0/bits/allocator.h:196:9:
                  │  196 |         if (std::__is_constant_evaluated())
                  │      |         ^~
                  │      |         |
                  │      |         (4) following ‘false’ branch... ─>─┐
                  │      |                                            │
                  │......
                  │      |                                            │
                  │      |┌───────────────────────────────────────────┘
                  │  203 |│        return __allocator_base<_Tp>::allocate(__n,
0);
                  │      |│              
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  │      |│                                              |
                  │      |└─────────────────────────────────────────────>(5)
...to here
                  │
    <─────────────┘
    │
  ‘_Tp* std::__new_allocator<_Tp>::allocate(size_type, const void*) [with _Tp =
std::__detail::_Hash_node<std::pair<const int, int>, false>]’: event 6
    │
    │/opt/gcc-15/include/c++/15.2.0/bits/new_allocator.h:134:53:
    │  134 |         if (__builtin_expect(__n > this->_M_max_size(), false))
    │      |                                                     ^
    │      |                                                     |
    │      |                                                     (6) inlined
call to ‘std::__new_allocator<std::__detail::_Hash_node<std::pair<const int,
int>, false> >::_M_max_size’ from
‘std::__new_allocator<std::__detail::_Hash_node<std::pair<const int, int>,
false> >::allocate’
    │
    └──> ‘constexpr std::__new_allocator<_Tp>::size_type
std::__new_allocator<_Tp>::_M_max_size() const [with _Tp =
std::__detail::_Hash_node<std::pair<const int, int>, false>]’: event 7
           │
           │  233 |         return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
           │      |                                                         ^
           │      |                                                         |
           │      |                                                         (7)
⚠️  ‘__a->std::__new_allocator<std::__detail::_Hash_node<std::pair<const int,
int>, false> >::allocate(__n, 0)’ leaks here
           │
In member function ‘constexpr std::__new_allocator<_Tp>::size_type
std::__new_allocator<_Tp>::_M_max_size() const [with _Tp =
std::__detail::_Hash_node_base*]’,
    inlined from ‘_Tp* std::__new_allocator<_Tp>::allocate(size_type, const
void*) [with _Tp = std::__detail::_Hash_node_base*]’ at
/opt/gcc-15/include/c++/15.2.0/bits/new_allocator.h:134:46:
/opt/gcc-15/include/c++/15.2.0/bits/new_allocator.h:233:57: warning: leak of
‘__alloc.std::__new_allocator<std::__detail::_Hash_node_base*>::allocate(__n,
0)’ [CWE-401] [-Wanalyzer-malloc-leak]
  233 |         return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
      |                                                         ^
  ‘std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_base**
std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_buckets(std::size_t)
[with _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const
int, int>, false> >]’: events 1-2
    │
    │/opt/gcc-15/include/c++/15.2.0/bits/hashtable_policy.h:1600:5:
    │ 1600 |     _Hashtable_alloc<_NodeAlloc>::_M_allocate_buckets(size_t
__bkt_count)
    │      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    │      |     |
    │      |     (1) entry to
‘std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const
int, int>, false> > >::_M_allocate_buckets’
    │......
    │ 1605 |       auto __ptr = __buckets_alloc_traits::allocate(__alloc,
__bkt_count);
    │      |                                                    ~
    │      |                                                    |
    │      |                                                    (2) inlined
call to ‘std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*>
>::allocate’ from
‘std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const
int, int>, false> > >::_M_allocate_buckets’
    │
    └──> ‘static constexpr _Tp* std::allocator_traits<std::allocator<_Up>
>::allocate(allocator_type&, size_type) [with _Tp =
std::__detail::_Hash_node_base*]’: event 3
           │
           │/opt/gcc-15/include/c++/15.2.0/bits/alloc_traits.h:614:28:
           │  614 |       { return __a.allocate(__n); }
           │      |                            ^
           │      |                            |
           │      |                            (3) inlined call to
‘std::allocator<std::__detail::_Hash_node_base*>::allocate’ from
‘std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*>
>::allocate’
           │
           └──> ‘constexpr _Tp* std::allocator< <template-parameter-1-1>
>::allocate(std::size_t) [with _Tp = std::__detail::_Hash_node_base*]’: events
4-5
                  │
                  │/opt/gcc-15/include/c++/15.2.0/bits/allocator.h:196:9:
                  │  196 |         if (std::__is_constant_evaluated())
                  │      |         ^~
                  │      |         |
                  │      |         (4) following ‘false’ branch... ─>─┐
                  │      |                                            │
                  │......
                  │      |                                            │
                  │      |┌───────────────────────────────────────────┘
                  │  203 |│        return __allocator_base<_Tp>::allocate(__n,
0);
                  │      |│              
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  │      |│                                              |
                  │      |└─────────────────────────────────────────────>(5)
...to here
                  │
    <─────────────┘
    │
  ‘_Tp* std::__new_allocator<_Tp>::allocate(size_type, const void*) [with _Tp =
std::__detail::_Hash_node_base*]’: event 6
    │
    │/opt/gcc-15/include/c++/15.2.0/bits/new_allocator.h:134:53:
    │  134 |         if (__builtin_expect(__n > this->_M_max_size(), false))
    │      |                                                     ^
    │      |                                                     |
    │      |                                                     (6) inlined
call to ‘std::__new_allocator<std::__detail::_Hash_node_base*>::_M_max_size’
from ‘std::__new_allocator<std::__detail::_Hash_node_base*>::allocate’
    │
    └──> ‘constexpr std::__new_allocator<_Tp>::size_type
std::__new_allocator<_Tp>::_M_max_size() const [with _Tp =
std::__detail::_Hash_node_base*’: event 7
           │
           │  233 |         return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
           │      |                                                         ^
           │      |                                                         |
           │      |                                                         (7)
⚠️ 
‘__alloc.std::__new_allocator<std::__detail::_Hash_node_base*>::allocate(__n,
0)’ leaks here
           │

Reply via email to