https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120288
Bug ID: 120288
Summary: spurious null pointer dereference in
std::__detail::_Hashtable_base::_M_key_equals since
gcc-15
Product: gcc
Version: 15.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: adl at gnu dot org
Target Milestone: ---
Created attachment 61428
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61428&action=edit
preprocessed sources
The following code produces spurious "potential null pointer dereference" with
GCC 15.1 and Debian's gcc-snapshot (20250502).
Those false positives where not produced with GCC 14.2 and earlier.
I found it quite hard to reduce the problem, because the diagnostics were only
pointing to the C++ headers, without any indication of what part of my code
called that method.
https://godbolt.org/z/s7W46dqnj
% cat foo.cc
#include <unordered_map>
class key
{
};
bool less_than(const key* left, const key* right) noexcept;
struct hash
{
size_t
operator()(const key*) const noexcept
{
return 0;
}
};
struct equal
{
bool
operator()(const key* left, const key* right) const noexcept
{
return less_than(left, right);
}
};
class foo
{
public:
foo();
private:
std::unordered_map<const key*, int, hash, equal> map;
};
foo::foo()
{
key b;
map.find(&b);
}
% g++ -O -Wnull-dereference -Werror -c foo.cc
In file included from /usr/lib/gcc-snapshot/include/c++/16/bits/hashtable.h:37,
from
/usr/lib/gcc-snapshot/include/c++/16/bits/unordered_map.h:33,
from /usr/lib/gcc-snapshot/include/c++/16/unordered_map:43,
from foo.cc:1:
In member function 'bool std::__detail::_Hashtable_base<_Key, _Value,
_ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _Traits>::_M_key_equals(const
_Key&, const std::__detail::_Hash_node_value<_Value, typename
_Traits::__hash_cached::value>&) const [with _Key = const key*; _Value =
std::pair<const key* const, int>; _ExtractKey = std::__detail::_Select1st;
_Equal = equal; _Hash = hash; _RangeHash = std::__detail::_Mod_range_hashing;
_Unused = std::__detail::_Default_ranged_hash; _Traits =
std::__detail::_Hashtable_traits<false, false, true>]',
inlined from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
_Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__location_type
std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash,
_Unused, _RehashPolicy, _Traits>::_M_locate(const key_type&) const [with _Key =
const key*; _Value = std::pair<const key* const, int>; _Alloc =
std::allocator<std::pair<const key* const, int> >; _ExtractKey =
std::__detail::_Select1st; _Equal = equal; _Hash = hash; _RangeHash =
std::__detail::_Mod_range_hashing; _Unused =
std::__detail::_Default_ranged_hash; _RehashPolicy =
std::__detail::_Prime_rehash_policy; _Traits =
std::__detail::_Hashtable_traits<false, false, true>]' at
/usr/lib/gcc-snapshot/include/c++/16/bits/hashtable.h:2272:31,
inlined from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
_Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::iterator
std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash,
_Unused, _RehashPolicy, _Traits>::find(const key_type&) [with _Key = const
key*; _Value = std::pair<const key* const, int>; _Alloc =
std::allocator<std::pair<const key* const, int> >; _ExtractKey =
std::__detail::_Select1st; _Equal = equal; _Hash = hash; _RangeHash =
std::__detail::_Mod_range_hashing; _Unused =
std::__detail::_Default_ranged_hash; _RehashPolicy =
std::__detail::_Prime_rehash_policy; _Traits =
std::__detail::_Hashtable_traits<false, false, true>]' at
/usr/lib/gcc-snapshot/include/c++/16/bits/hashtable.h:1918:32:
/usr/lib/gcc-snapshot/include/c++/16/bits/hashtable_policy.h:1409:23: error:
potential null pointer dereference [-Werror=null-dereference]
1409 | return _M_eq()(__k, _ExtractKey{}(__n._M_v()));
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors