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

            Bug ID: 120466
           Summary: Analyzer report for C++ 'std::stringbuf' instantiation
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: analyzer
          Assignee: dmalcolm at gcc dot gnu.org
          Reporter: tschwinge at gcc dot gnu.org
  Target Milestone: ---

Given:

    #include <sstream>
    void f()
    {
      std::stringbuf out_b;
    }

..., '-fanalyzer' reports:

    In file included from
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/c++allocator.h:33,
                     from
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/allocator.h:46,
                     from
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/string:45,
                     from
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/locale_classes.h:42,
                     from
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/ios_base.h:43,
                     from
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/ios:46,
                     from
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/istream:42,
                     from
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/sstream:42,
                     from [...]/a.C:1:
   
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/new_allocator.h:
In member function ‘void std::__new_allocator<_Tp>::deallocate(_Tp*, size_type)
[with _Tp = char]’:
   
[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/new_allocator.h:172:66:
warning: ‘delete’ of ‘__p’ which points to memory on the stack [CWE-590]
[-Wanalyzer-free-of-non-heap]
      172 |         _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
          |                                                                  ^
      ‘void f()’: events 1-3
        |
        |[...]/a.C:2:6:
        |    2 | void f()
        |      |      ^
        |      |      |
        |      |      (1) entry to ‘f’
        |    3 | {
        |    4 |   std::stringbuf out_b;
        |      |                  ~~~~~
        |      |                  |
        |      |                  (2) region created on stack here
        |    5 | }
        |      | ~     
        |      | |
        |      | (3) calling
‘std::__cxx11::basic_stringbuf<char>::~basic_stringbuf’ from ‘f’
        |
        +--> ‘std::__cxx11::basic_stringbuf<char>::~basic_stringbuf()’: events
4-5
               |
              
|[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/sstream:81:11:
               |   81 |     class basic_stringbuf : public
basic_streambuf<_CharT, _Traits>
               |      |           ^~~~~~~~~~~~~~~
               |      |           |
               |      |           (4) entry to
‘std::__cxx11::basic_stringbuf<char>::~basic_stringbuf’
               |      |           (5) calling
‘std::__cxx11::basic_string<char>::~basic_string’ from
‘std::__cxx11::basic_stringbuf<char>::~basic_stringbuf’
               |
               +--> ‘constexpr std::__cxx11::basic_string<_CharT, _Traits,
_Alloc>::~basic_string() [with _CharT = char; _Traits = std::char_traits<char>;
_Alloc = std::allocator<char>]’: events 6-7
                      |
                     
|[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:895:7:
                      |  895 |       ~basic_string()
                      |      |       ^
                      |      |       |
                      |      |       (6) entry to
‘std::__cxx11::basic_string<char>::~basic_string’
                      |  896 |       { _M_dispose(); }
                      |      |         ~~~~~~~~~~~~
                      |      |                   |
                      |      |                   (7) calling
‘std::__cxx11::basic_string<char>::_M_dispose’ from
‘std::__cxx11::basic_string<char>::~basic_string’
                      |
                      +--> ‘constexpr void std::__cxx11::basic_string<_CharT,
_Traits, _Alloc>::_M_dispose() [with _CharT = char; _Traits =
std::char_traits<char>; _Alloc = std::allocator<char>]’: events 8-9
                             |
                             |  296 |       _M_dispose()
                             |      |       ^~~~~~~~~~
                             |      |       |
                             |      |       (8) entry to
‘std::__cxx11::basic_string<char>::_M_dispose’
                             |  297 |       {
                             |  298 |         if (!_M_is_local())
                             |      |              ~~~~~~~~~~~~~
                             |      |                         |
                             |      |                         (9) calling
‘std::__cxx11::basic_string<char>::_M_is_local’ from
‘std::__cxx11::basic_string<char>::_M_dispose’
                             |
                             +--> ‘constexpr bool
std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_M_is_local() const [with
_CharT = char; _Traits = std::char_traits<char>; _Alloc =
std::allocator<char>]’: events 10-12
                                    |
                                    |  278 |       _M_is_local() const
                                    |      |       ^~~~~~~~~~~
                                    |      |       |
                                    |      |       (10) entry to
‘std::__cxx11::basic_string<char>::_M_is_local’
                                    |  279 |       {
                                    |  280 |         if (_M_data() ==
_M_local_data())
                                    |      |         ~~
                                    |      |         |
                                    |      |         (11) following ‘false’
branch... ->-+
                                    |      |                                   
         |
                                    |......
                                    |      |                                   
         |
                                    |     
|+--------------------------------------------+
                                    |  286 ||        return false;
                                    |      ||               ~~~~~
                                    |      ||               |
                                    |      |+-------------->(12) ...to here
                                    |
                             <------+
                             |
                           ‘constexpr void std::__cxx11::basic_string<_CharT,
_Traits, _Alloc>::_M_dispose() [with _CharT = char; _Traits =
std::char_traits<char>; _Alloc = std::allocator<char>]’: event 13
                             |
                             |  298 |         if (!_M_is_local())
                             |      |              ~~~~~~~~~~~^~
                             |      |                         |
                             |      |                         (13) returning to
‘std::__cxx11::basic_string<char>::_M_dispose’ from
‘std::__cxx11::basic_string<char>::_M_is_local’
                             |
                           ‘constexpr void std::__cxx11::basic_string<_CharT,
_Traits, _Alloc>::_M_dispose() [with _CharT = char; _Traits =
std::char_traits<char>; _Alloc = std::allocator<char>]’: events 14-16
                             |
                             |  298 |         if (!_M_is_local())
                             |      |         ^~
                             |      |         |
                             |      |         (14) following ‘true’ branch...
->-+
                             |      |                                          
 |
                             |      |                                          
 |
                             |     
|+-------------------------------------------+
                             |  299 ||         
_M_destroy(_M_allocated_capacity);
                             |      ||         
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                             |      ||                    |
                             |      |+------------------->(15) ...to here
                             |      |                     (16) calling
‘std::__cxx11::basic_string<char>::_M_destroy’ from
‘std::__cxx11::basic_string<char>::_M_dispose’
                             |
                             +--> ‘constexpr void
std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_M_destroy(size_type)
[with _CharT = char; _Traits = std::char_traits<char>; _Alloc =
std::allocator<char>]’: events 17-18
                                    |
                                    |  304 |       _M_destroy(size_type __size)
throw()
                                    |      |       ^~~~~~~~~~
                                    |      |       |
                                    |      |       (17) entry to
‘std::__cxx11::basic_string<char>::_M_destroy’
                                    |  305 |       {
_Alloc_traits::deallocate(_M_get_allocator(), _M_data(), __size + 1); }
                                    |      |                                  ~
                                    |      |                                  |
                                    |      |                                 
(18) inlined call to ‘std::allocator_traits<std::allocator<char> >::deallocate’
from ‘std::__cxx11::basic_string<char>::_M_destroy’
                                    |
                                    +--> ‘static constexpr void
std::allocator_traits<std::allocator<_CharT> >::deallocate(allocator_type&,
pointer, size_type) [with _Tp = char]’: event 19
                                           |
                                          
|[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/alloc_traits.h:649:23:
                                           |  649 |       { __a.deallocate(__p,
__n); }
                                           |      |                       ^
                                           |      |                       |
                                           |      |                       (19)
inlined call to ‘std::allocator<char>::deallocate’ from
‘std::allocator_traits<std::allocator<char> >::deallocate’
                                           |
                                           +--> ‘constexpr void std::allocator<
<template-parameter-1-1> >::deallocate(_Tp*, std::size_t) [with _Tp = char]’:
event 20
                                                  |
                                                 
|[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/allocator.h:215:42:
                                                  |  215 |        
__allocator_base<_Tp>::deallocate(__p, __n);
                                                  |      |        
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
                                                  |      |                     
                    |
                                                  |      |                     
                    (20) calling ‘std::__new_allocator<char>::deallocate’ from
‘std::__cxx11::basic_string<char>::_M_destroy’
                                                  |
                                           <------+
                                           |
                                         ‘void
std::__new_allocator<_Tp>::deallocate(_Tp*, size_type) [with _Tp = char]’:
events 21-22
                                           |
                                          
|[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/new_allocator.h:156:7:
                                           |  156 |       deallocate(_Tp* __p,
size_type __n __attribute__ ((__unused__)))
                                           |      |       ^~~~~~~~~~
                                           |      |       |
                                           |      |       (21) entry to
‘std::__new_allocator<char>::deallocate’
                                           |......
                                           |  172 |        
_GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
                                           |      |                            
                                     ~
                                           |      |                            
                                     |
                                           |      |                            
                                     (22) call to ‘delete’ here
                                           |

Is that a false positive to be fixed in the analyzer (perhaps just C++ idioms
not supported yet), or is there an actual in the libstdc++ code?

Reply via email to