https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87805
Bug ID: 87805
Summary: Incomplete diagnostic for -Wnoexcept
Product: gcc
Version: 8.2.0
Status: UNCONFIRMED
Keywords: diagnostic
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: reichelt at gcc dot gnu.org
Target Milestone: ---
The warning option "-Wnoexcept" produces incomplete diagnostics
for the following testcase:
==================================================
#include <unordered_set>
struct Hash
{
char operator()(char) const { return 0; }
};
std::unordered_set<char, Hash> x;
==================================================
==================================================
/gcc-8.2.0/include/c++/8.2.0/type_traits: In instantiation of 'constexpr bool
std::__call_is_nt(std::__invoke_other) [with _Fn = const Hash&; _Args = {const
char&}]':
/gcc-8.2.0/include/c++/8.2.0/type_traits:2658:34: required by substitution of
'template<bool __v> using __bool_constant = std::integral_constant<bool, __v>
[with bool __v = std::__call_is_nt<const Hash&, const
char&>((std::__result_of_success<char, std::__invoke_other>::__invoke_type{},
std::__result_of_success<char, std::__invoke_other>::__invoke_type()))]'
/gcc-8.2.0/include/c++/8.2.0/type_traits:2656:12: required from 'struct
std::__call_is_nothrow<std::__invoke_result<const Hash&, const char&>, const
Hash&, const char&>'
/gcc-8.2.0/include/c++/8.2.0/type_traits:131:12: required from 'struct
std::__and_<std::__is_invocable<const Hash&, const char&>,
std::__call_is_nothrow<std::__invoke_result<const Hash&, const char&>, const
Hash&, const char&> >'
/gcc-8.2.0/include/c++/8.2.0/type_traits:2668:12: required from 'struct
std::__is_nothrow_invocable<const Hash&, const char&>'
/gcc-8.2.0/include/c++/8.2.0/type_traits:131:12: required from 'struct
std::__and_<std::__is_fast_hash<Hash>, std::__is_nothrow_invocable<const Hash&,
const char&> >'
/gcc-8.2.0/include/c++/8.2.0/type_traits:142:31: required from 'struct
std::__not_<std::__and_<std::__is_fast_hash<Hash>,
std::__is_nothrow_invocable<const Hash&, const char&> > >'
/gcc-8.2.0/include/c++/8.2.0/bits/unordered_set.h:99:63: required from 'class
std::unordered_set<char, Hash>'
bug.cc:8:32: required from here
bug.cc:5:8: warning: but 'char Hash::operator()(char) const' does not throw;
perhaps it should be declared 'noexcept' [-Wnoexcept]
char operator()(char) const { return 0; }
^~~~~~~~
==================================================
Only with the additional option "-Wsystem-headers" you get the complete
diagnostics:
==================================================
In file included from /gcc-8.2.0/include/c++/8.2.0/unordered_set:38,
from bug.cc:1:
/gcc-8.2.0/include/c++/8.2.0/type_traits: In instantiation of 'constexpr bool
std::__call_is_nt(std::__invoke_other) [with _Fn = const Hash&; _Args = {const
char&}]':
/gcc-8.2.0/include/c++/8.2.0/type_traits:2658:34: required by substitution of
'template<bool __v> using __bool_constant = std::integral_constant<bool, __v>
[with bool __v = std::__call_is_nt<const Hash&, const
char&>((std::__result_of_success<char, std::__invoke_other>::__invoke_type{},
std::__result_of_success<char, std::__invoke_other>::__invoke_type()))]'
/gcc-8.2.0/include/c++/8.2.0/type_traits:2656:12: required from 'struct
std::__call_is_nothrow<std::__invoke_result<const Hash&, const char&>, const
Hash&, const char&>'
/gcc-8.2.0/include/c++/8.2.0/type_traits:131:12: required from 'struct
std::__and_<std::__is_invocable<const Hash&, const char&>,
std::__call_is_nothrow<std::__invoke_result<const Hash&, const char&>, const
Hash&, const char&> >'
/gcc-8.2.0/include/c++/8.2.0/type_traits:2668:12: required from 'struct
std::__is_nothrow_invocable<const Hash&, const char&>'
/gcc-8.2.0/include/c++/8.2.0/type_traits:131:12: required from 'struct
std::__and_<std::__is_fast_hash<Hash>, std::__is_nothrow_invocable<const Hash&,
const char&> >'
/gcc-8.2.0/include/c++/8.2.0/type_traits:142:31: required from 'struct
std::__not_<std::__and_<std::__is_fast_hash<Hash>,
std::__is_nothrow_invocable<const Hash&, const char&> > >'
/gcc-8.2.0/include/c++/8.2.0/bits/unordered_set.h:99:63: required from 'class
std::unordered_set<char, Hash>'
bug.cc:8:32: required from here
/gcc-8.2.0/include/c++/8.2.0/type_traits:2652:68: warning: noexcept-expression
evaluates to 'false' because of a call to 'char Hash::operator()(char) const'
[-Wnoexcept]
return noexcept(std::declval<_Fn>()(std::declval<_Args>()...));
^
bug.cc:5:8: warning: but 'char Hash::operator()(char) const' does not throw;
perhaps it should be declared 'noexcept' [-Wnoexcept]
char operator()(char) const { return 0; }
^~~~~~~~
==================================================
The culprit seems to be the function maybe_noexcept_warning from cp/except.c
where both parts of the warning are emitted as separate warnings.
The first part is (wrongly) suppressed when it is located in a system header:
static void
maybe_noexcept_warning (tree fn)
{
if (TREE_NOTHROW (fn))
{
warning (OPT_Wnoexcept, "noexcept-expression evaluates to %<false%> "
"because of a call to %qD", fn);
warning_at (DECL_SOURCE_LOCATION (fn), OPT_Wnoexcept,
"but %qD does not throw; perhaps "
"it should be declared %<noexcept%>", fn);
}
}