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(-) 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); } base-commit: 69d82c1dccb3583464228eb5449e29918eeb4ee4 -- 2.46.0