Commit 5035cd66 by Jason Merrill

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.
parent cf17dcc6
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.
......
......@@ -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);
}
}
......
// 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);
}
// -*- 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;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment