extern void start_decl_1 (tree, bool);
extern bool check_array_initializer (tree, tree, tree);
extern void omp_declare_variant_finalize (tree, tree);
+extern void maybe_diagnose_deallocation_noexcept_false (tree);
struct cp_decomp { tree decl; unsigned int count; };
extern void cp_finish_decl (tree, tree, bool, tree, int, cp_decomp * = nullptr);
extern tree lookup_decomp_type (tree);
}
}
+/* [basic.stc.dynamic.deallocation]/3 - A deallocation function shall not
+ have a potentially throwing exception specification. */
+
+void
+maybe_diagnose_deallocation_noexcept_false (tree decl)
+{
+ if (cxx_dialect >= cxx29
+ && DECL_NAME (decl)
+ && IDENTIFIER_NEWDEL_OP_P (DECL_NAME (decl))
+ && !IDENTIFIER_NEW_OP_P (DECL_NAME (decl)))
+ {
+ tree spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl));
+ if (spec && spec == noexcept_false_spec)
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "deallocation function %qD declared possibly throwing",
+ decl);
+ }
+}
+
static void cp_maybe_mangle_decomp (tree, cp_decomp *);
/* Finish processing of a declaration;
}
}
+ /* [basic.stc.dynamic.deallocation]/3 - A deallocation function shall not
+ have a potentially throwing exception specification. */
+ maybe_diagnose_deallocation_noexcept_false (decl);
+
/* Caller will do the rest of this. */
if (check < 0)
{
/* Remove any template parameters from the symbol table. */
maybe_end_member_template_processing ();
+
+ /* [basic.stc.dynamic.deallocation]/3 - A deallocation function
+ shall not have a potentially throwing exception specification. */
+ maybe_diagnose_deallocation_noexcept_false (decl);
}
vec_safe_truncate (unparsed_noexcepts, 0);
if (orig_fn)
TREE_TYPE (orig_fn) = TREE_TYPE (fn);
+ /* [basic.stc.dynamic.deallocation]/3 - A deallocation function shall not
+ have a potentially throwing exception specification. */
+ maybe_diagnose_deallocation_noexcept_false (fn);
+
return true;
}
struct A {};
void operator delete (void *, A);
void operator delete (void *, A) noexcept (false); // { dg-error "declaration of 'void operator delete\\\(void\\\*, A\\\) noexcept \\\(false\\\)' has a different exception specifier" }
+// { dg-error "deallocation function 'void operator delete\\\(void\\\*, A\\\)' declared possibly throwing" "" { target c++29 } .-1 }
struct B {};
-void operator delete (void *, B) noexcept (false);
+void operator delete (void *, B) noexcept (false); // { dg-error "deallocation function 'void operator delete\\\(void\\\*, B\\\)' declared possibly throwing" "" { target c++29 } }
void operator delete (void *, B); // { dg-error "declaration of 'void operator delete\\\(void\\\*, B\\\) noexcept' has a different exception specifier" }
--- /dev/null
+// P3424R2 - Deallocation Functions with Throwing Exception Specification Are Ill-formed
+// { dg-do compile { target c++11 } }
+
+struct A {};
+struct B {};
+void operator delete (void *, A) noexcept (false); // { dg-error "deallocation function 'void operator delete\\\(void\\\*, A\\\)' declared possibly throwing" "" { target c++29 } }
+void operator delete (void *, B) noexcept (false) {} // { dg-error "deallocation function 'void operator delete\\\(void\\\*, B\\\)' declared possibly throwing" "" { target c++29 } }
+void operator delete[] (void *, A) noexcept (false); // { dg-error "deallocation function 'void operator delete \\\[\\\]\\\(void\\\*, A\\\)' declared possibly throwing" "" { target c++29 } }
+void operator delete[] (void *, B) noexcept (false) {} // { dg-error "deallocation function 'void operator delete \\\[\\\]\\\(void\\\*, B\\\)' declared possibly throwing" "" { target c++29 } }
+template <bool T, bool U>
+struct C {
+ static void operator delete (void *) noexcept (T); // { dg-error "deallocation function 'static void C<T, U>::operator delete\\\(void\\\*\\\) \\\[with bool T = false; bool U = true\\\]' declared possibly throwing" "" { target c++29 } }
+ static void operator delete[] (void *) noexcept (T); // { dg-error "deallocation function 'static void C<T, U>::operator delete \\\[\\\]\\\(void\\\*\\\) \\\[with bool T = false; bool U = true\\\]' declared possibly throwing" "" { target c++29 } }
+};
+template <bool T, bool U>
+struct D {
+ static void operator delete (void *) noexcept (T) {} // { dg-error "deallocation function 'static void D<T, U>::operator delete\\\(void\\\*\\\) \\\[with bool T = false; bool U = true\\\]' declared possibly throwing" "" { target c++29 } }
+ static void operator delete[] (void *) noexcept (T) {}// { dg-error "deallocation function 'static void D<T, U>::operator delete \\\[\\\]\\\(void\\\*\\\) \\\[with bool T = false; bool U = true\\\]' declared possibly throwing" "" { target c++29 } }
+};
+C <false, false> a;
+C <true, false> b;
+D <false, false> c;
+D <true, false> d;
+auto e = &C <false, true>::operator delete;
+auto f = &C <true, true>::operator delete;
+auto g = &D <false, true>::operator delete;
+auto h = &D <true, true>::operator delete;
+auto i = &C <false, true>::operator delete[];
+auto j = &C <true, true>::operator delete[];
+auto k = &D <false, true>::operator delete[];
+auto l = &D <true, true>::operator delete[];
+struct E {
+ static void operator delete (void *) noexcept (C) {} // { dg-error "deallocation function 'static void E::operator delete\\\(void\\\*\\\)' declared possibly throwing" "" { target c++29 } }
+ static constexpr bool C = false;
+};
+template <int N>
+struct F {
+ static void operator delete (void *) noexcept (false); // { dg-error "deallocation function 'static void F<N>::operator delete\\\(void\\\*\\\)' declared possibly throwing" "" { target c++29 } }
+ static void operator delete[] (void *) noexcept (false); // { dg-error "deallocation function 'static void F<N>::operator delete \\\[\\\]\\\(void\\\*\\\)' declared possibly throwing" "" { target c++29 } }
+};
+template <int N>
+struct G {
+ static void operator delete (void *) noexcept (false) {} // { dg-error "deallocation function 'static void G<N>::operator delete\\\(void\\\*\\\)' declared possibly throwing" "" { target c++29 } }
+ static void operator delete[] (void *) noexcept (false) {} // { dg-error "deallocation function 'static void G<N>::operator delete \\\[\\\]\\\(void\\\*\\\)' declared possibly throwing" "" { target c++29 } }
+};