diff mbox series

[pushed] c++: exception spec and stdlib specialization

Message ID 20240907225505.3414902-1-jason@redhat.com
State New
Headers show
Series [pushed] c++: exception spec and stdlib specialization | expand

Commit Message

Jason Merrill Sept. 7, 2024, 10:54 p.m. UTC
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

We were silently accepting the pr65923.C specialization of std::swap with
the wrong exception specification; it should be declared noexcept.  Let's
limit ignoring mismatch with system headers to extern "C" functions so we
get a diagnostic for the C++ library.

In the case of an omitted exception-specification, let's also lower the
error to a pedwarn, and copy the missing spec over, to avoid a hard break
for code that accidentally relied on the old behavior.

...except extern "C" functions keep the new spec, to avoid breaking dubious
code like noexcept-type19.C.

gcc/cp/ChangeLog:

	* decl.cc (check_redeclaration_exception_specification): Remove
	OPT_Wsystem_headers from pedwarn when the old declaration is
	in a system header.  Also check std namespace.

gcc/testsuite/ChangeLog:

	* g++.dg/diagnostic/pr65923.C: Add noexcept.
	* g++.dg/cpp1z/aligned-new3.C: Expect pedwarn.
	* g++.dg/cpp1z/noexcept-type19.C: Add comment.
---
 gcc/cp/decl.cc                               | 20 ++++++++++++++++++--
 gcc/testsuite/g++.dg/cpp1z/aligned-new3.C    |  3 ++-
 gcc/testsuite/g++.dg/cpp1z/noexcept-type19.C |  2 +-
 gcc/testsuite/g++.dg/diagnostic/pr65923.C    |  2 +-
 4 files changed, 22 insertions(+), 5 deletions(-)


base-commit: 69d82c1dccb3583464228eb5449e29918eeb4ee4
diff mbox series

Patch

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index f0271308d92..2190ede745b 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1395,17 +1395,33 @@  check_redeclaration_exception_specification (tree new_decl,
       bool complained = true;
       location_t new_loc = DECL_SOURCE_LOCATION (new_decl);
       auto_diagnostic_group d;
-      if (DECL_IN_SYSTEM_HEADER (old_decl))
+
+      if (DECL_IN_SYSTEM_HEADER (old_decl) && DECL_EXTERN_C_P (old_decl))
+	/* Don't fuss about the C library; the C library functions are not
+	   specified to have exception specifications (just behave as if they
+	   have them), but some implementations include them.  */
 	complained = pedwarn (new_loc, OPT_Wsystem_headers, msg, new_decl);
       else if (!flag_exceptions)
 	/* We used to silently permit mismatched eh specs with
-	   -fno-exceptions, so make them a pedwarn now.  */
+	   -fno-exceptions, so only complain if -pedantic.  */
 	complained = pedwarn (new_loc, OPT_Wpedantic, msg, new_decl);
+      else if (!new_exceptions)
+	/* Reduce to pedwarn for omitted exception specification.  No warning
+	   flag for this; silence the warning by correcting the code.  */
+	complained = pedwarn (new_loc, 0, msg, new_decl);
       else
 	error_at (new_loc, msg, new_decl);
+
       if (complained)
 	inform (DECL_SOURCE_LOCATION (old_decl),
 		"from previous declaration %qF", old_decl);
+
+      /* Copy the old exception specification if new_decl has none.  Unless the
+	 old decl is extern "C", as obscure code might depend on the type of
+	 the new declaration (e.g. noexcept-type19.C).  */
+      if (!new_exceptions && !DECL_EXTERN_C_P (old_decl))
+	TREE_TYPE (new_decl)
+	  = build_exception_variant (TREE_TYPE (new_decl), old_exceptions);
     }
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C b/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C
index 08cd732ac7b..165c3771ab9 100644
--- a/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C
+++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C
@@ -1,4 +1,5 @@ 
 // { dg-do run { target c++17 } }
+// { dg-options "" }
 
 #include <new>
 
@@ -12,7 +13,7 @@  void* operator new (std::size_t n, std::align_val_t)
 }
 
 bool deleted = false;
-void operator delete (void *p, std::size_t, std::align_val_t)
+void operator delete (void *p, std::size_t, std::align_val_t) // { dg-warning "exception specifier" }
 {
   deleted = true;
   operator delete (p);
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.C
index 571c426aa67..9beadd08298 100644
--- a/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.C
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.C
@@ -2,7 +2,7 @@ 
 
 #include "noexcept-type19.h"
 
-extern "C" void *malloc (size_t);
+extern "C" void *malloc (size_t); // silently discard throw() from system header
 
 template<class T> void f(T*);
 
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr65923.C b/gcc/testsuite/g++.dg/diagnostic/pr65923.C
index 036f4478181..40b6b5965fa 100644
--- a/gcc/testsuite/g++.dg/diagnostic/pr65923.C
+++ b/gcc/testsuite/g++.dg/diagnostic/pr65923.C
@@ -16,7 +16,7 @@  struct X2
 
 namespace std
 {
-  template<> void swap(X&, X&)
+  template<> void swap(X&, X&) noexcept
   {
     constexpr std::chrono::duration<long double> operator""s(long double);
   }