aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2024-09-06 15:28:53 -0400
committerJason Merrill <jason@redhat.com>2024-09-07 18:54:13 -0400
commit7cebc6384a0ad63d444029472a8ed1afe965bbbc (patch)
treeb409b60ed2ec77c5484dc1b6471266cbbac3ec8f
parent69d82c1dccb3583464228eb5449e29918eeb4ee4 (diff)
downloadgcc-7cebc6384a0ad63d444029472a8ed1afe965bbbc.zip
gcc-7cebc6384a0ad63d444029472a8ed1afe965bbbc.tar.gz
gcc-7cebc6384a0ad63d444029472a8ed1afe965bbbc.tar.bz2
c++: exception spec and stdlib specialization
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.
-rw-r--r--gcc/cp/decl.cc20
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/aligned-new3.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type19.C2
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr65923.C2
4 files changed, 22 insertions, 5 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index f027130..2190ede 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 08cd732..165c377 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 571c426..9beadd0 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 036f447..40b6b59 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);
}