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); } }