diff options
author | Jason Merrill <jason@redhat.com> | 2020-01-26 00:37:24 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-01-26 21:26:17 -0500 |
commit | 5035cd662459b09605370f2ba41b2238119c69b1 (patch) | |
tree | 92714a88784da28de205aa1159b73407cf1601cd | |
parent | cf17dcc6fc1f9f69d592952c2dd5796a5665bd5a (diff) | |
download | gcc-5035cd662459b09605370f2ba41b2238119c69b1.zip gcc-5035cd662459b09605370f2ba41b2238119c69b1.tar.gz gcc-5035cd662459b09605370f2ba41b2238119c69b1.tar.bz2 |
c++: Fix -Wnoexcept handling of system headers (PR90992).
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.
PR c++/90992
* except.c (maybe_noexcept_warning): Check DECL_IN_SYSTEM_HEADER and
temporarily enable -Wsystem-headers. Change second warning to
conditional inform.
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/except.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wnoexcept1.C | 34 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wnoexcept1.h | 37 |
4 files changed, 86 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0b17aba..b51d67f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2020-01-26 Jason Merrill <jason@redhat.com> + PR c++/90992 + * except.c (maybe_noexcept_warning): Check DECL_IN_SYSTEM_HEADER and + temporarily enable -Wsystem-headers. Change second warning to + conditional inform. + PR c++/90997 * semantics.c (finish_call_expr): Don't call instantiate_non_dependent_expr before warn_for_memset. diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 0b40234..788b96d 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 0000000..e3a5df6 --- /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); +} diff --git a/gcc/testsuite/g++.dg/warn/Wnoexcept1.h b/gcc/testsuite/g++.dg/warn/Wnoexcept1.h new file mode 100644 index 0000000..f59733e --- /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; +}; |