The immediate issue here was that the second warning didn't depend on the first one, so if the first location was in a system header, we'd mysteriously give the second by itself.
It's also the case that the thing we care about being in a system header is the function that we want to suggest adding 'noexcept' to, not the noexcept-expression; it's useful to suggest adding noexcept to a user function to satisfy a noexcept-expression in a system header. Tested x86_64-pc-linux-gnu, applying to trunk. PR c++/90992 * except.c (maybe_noexcept_warning): Check DECL_IN_SYSTEM_HEADER and temporarily enable -Wsystem-headers. Change second warning to conditional inform. --- gcc/testsuite/g++.dg/warn/Wnoexcept1.h | 37 ++++++++++++++++++++++++++ gcc/cp/except.c | 16 ++++++----- gcc/testsuite/g++.dg/warn/Wnoexcept1.C | 34 +++++++++++++++++++++++ 3 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wnoexcept1.h create mode 100644 gcc/testsuite/g++.dg/warn/Wnoexcept1.C diff --git a/gcc/testsuite/g++.dg/warn/Wnoexcept1.h b/gcc/testsuite/g++.dg/warn/Wnoexcept1.h new file mode 100644 index 00000000000..f59733e705f --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wnoexcept1.h @@ -0,0 +1,37 @@ +// -*- C++ -*- +#pragma GCC system_header + +using size_t = decltype(sizeof(42)); +inline void * operator new (size_t, void *p) noexcept { return p; } + +class NotNoexcept { +public: + NotNoexcept() noexcept(false) {} + NotNoexcept(const NotNoexcept&) noexcept(false) {} + NotNoexcept(NotNoexcept &&) noexcept(false) {} + ~NotNoexcept() noexcept(false) {} + + NotNoexcept&operator=(const NotNoexcept&) noexcept(false) { return *this;} + NotNoexcept&operator=(NotNoexcept &&) noexcept(false) {return *this;} +}; + +template<typename _Up, typename... _Args> +void +construct1(_Up* __p, _Args... __args) + noexcept(noexcept(::new((void *)__p) _Up(__args...))) +{ ::new((void *)__p) _Up(__args...); } + +template<typename _Up, typename... _Args> +void +construct2(_Up* __p, _Args... __args) + noexcept(noexcept(::new((void *)__p) _Up(__args...))) +{ ::new((void *)__p) _Up(__args...); } + +class Automatic1 { +public: + Automatic1(size_t bla) : Bla(bla) {}; + +private: + size_t Bla; + NotNoexcept Dummy; +}; diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 0b40234e228..788b96de243 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1165,13 +1165,17 @@ static GTY(()) vec<pending_noexcept, va_gc> *pending_noexcept_checks; static void maybe_noexcept_warning (tree fn) { - if (TREE_NOTHROW (fn)) + if (TREE_NOTHROW (fn) + && (!DECL_IN_SYSTEM_HEADER (fn) + || global_dc->dc_warn_system_headers)) { - 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); + temp_override<bool> s (global_dc->dc_warn_system_headers, true); + auto_diagnostic_group d; + if (warning (OPT_Wnoexcept, "noexcept-expression evaluates to %<false%> " + "because of a call to %qD", fn)) + inform (DECL_SOURCE_LOCATION (fn), + "but %qD does not throw; perhaps " + "it should be declared %<noexcept%>", fn); } } diff --git a/gcc/testsuite/g++.dg/warn/Wnoexcept1.C b/gcc/testsuite/g++.dg/warn/Wnoexcept1.C new file mode 100644 index 00000000000..e3a5df64459 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wnoexcept1.C @@ -0,0 +1,34 @@ +// PR c++/90992 +// { dg-do compile { target c++11 } } +// { dg-additional-options -Wnoexcept } + +#include "Wnoexcept1.h" + +// We expect a warning at the declaration of construct2, since Automatic2 is +// defined below; we don't expect one for construct1, because Automatic1 is +// defined in the fake system header. +// { dg-warning "noexcept-expression" "" { target *-*-* } 26 } + +class Automatic2 { +public: + Automatic2(size_t bla) : Bla(bla) {}; // { dg-message "noexcept" } + +private: + size_t Bla; + NotNoexcept Dummy; +}; + +union U +{ + unsigned char buf[sizeof(Automatic1)]; + Automatic1 a1; + Automatic2 a2; + U(): buf{} {} + ~U() {} +}; + +int main() { + U u; + construct1(&u.a1, 42); + construct2(&u.a2, 42); +} base-commit: cf17dcc6fc1f9f69d592952c2dd5796a5665bd5a -- 2.18.1