diff mbox series

[COMMITTED] c++: Fix -Wnoexcept handling of system headers (PR90992).

Message ID 20200127022811.28592-1-jason@redhat.com
State New
Headers show
Series [COMMITTED] c++: Fix -Wnoexcept handling of system headers (PR90992). | expand

Commit Message

Jason Merrill Jan. 27, 2020, 2:28 a.m. UTC
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


base-commit: cf17dcc6fc1f9f69d592952c2dd5796a5665bd5a
diff mbox series

Patch

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