From 593a083530a21d54d39929706ffdef2d98df8ae6 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Mon, 2 Apr 2012 00:13:30 +0000 Subject: [PATCH] re PR c++/50043 ([C++0x] Implement core/1123) /cp 2012-04-01 Paolo Carlini PR c++/50043 * class.c (deduce_noexcept_on_destructor, deduce_noexcept_on_destructors): New. (check_bases_and_members): Call the latter. * decl.c (grokfndecl): Call the former. * method.c (implicitly_declare_fn): Not static. * cp-tree.h (deduce_noexcept_on_destructor, implicitly_declare_fn): Declare /testsuite 2012-04-01 Paolo Carlini PR c++/50043 * g++.dg/cpp0x/noexcept17.C: New. * g++.old-deja/g++.eh/cleanup1.C: Adjust. * g++.dg/tree-ssa/ehcleanup-1.C: Likewise. * g++.dg/cpp0x/noexcept01.C: Likewise. * g++.dg/eh/init-temp1.C: Likewise. * g++.dg/eh/ctor1.C: Likwise. From-SVN: r186058 --- gcc/cp/ChangeLog | 11 ++++++ gcc/cp/class.c | 39 ++++++++++++++++++++ gcc/cp/cp-tree.h | 3 ++ gcc/cp/decl.c | 7 ++++ gcc/cp/method.c | 2 +- gcc/testsuite/ChangeLog | 10 ++++++ gcc/testsuite/g++.dg/cpp0x/noexcept01.C | 4 +-- gcc/testsuite/g++.dg/cpp0x/noexcept17.C | 54 ++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/eh/ctor1.C | 8 ++++- gcc/testsuite/g++.dg/eh/init-temp1.C | 8 ++++- gcc/testsuite/g++.dg/tree-ssa/ehcleanup-1.C | 9 ++++- gcc/testsuite/g++.old-deja/g++.eh/cleanup1.C | 8 ++++- 12 files changed, 156 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept17.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7e4e549..89ea02d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2012-04-01 Paolo Carlini + + PR c++/50043 + * class.c (deduce_noexcept_on_destructor, + deduce_noexcept_on_destructors): New. + (check_bases_and_members): Call the latter. + * decl.c (grokfndecl): Call the former. + * method.c (implicitly_declare_fn): Not static. + * cp-tree.h (deduce_noexcept_on_destructor, implicitly_declare_fn): + Declare + 2012-03-29 Paolo Carlini PR c++/52718 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index bc17c82..7b6559c 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4321,6 +4321,41 @@ clone_constructors_and_destructors (tree t) clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1); } +/* Deduce noexcept for a destructor DTOR. */ + +void +deduce_noexcept_on_destructor (tree dtor) +{ + if (!TYPE_RAISES_EXCEPTIONS (TREE_TYPE (dtor))) + { + tree ctx = DECL_CONTEXT (dtor); + tree implicit_fn = implicitly_declare_fn (sfk_destructor, ctx, + /*const_p=*/false); + tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn)); + TREE_TYPE (dtor) = build_exception_variant (TREE_TYPE (dtor), eh_spec); + } +} + +/* For each destructor in T, deduce noexcept: + + 12.4/3: A declaration of a destructor that does not have an + exception-specification is implicitly considered to have the + same exception-specification as an implicit declaration (15.4). */ + +static void +deduce_noexcept_on_destructors (tree t) +{ + tree fns; + + /* If for some reason we don't have a CLASSTYPE_METHOD_VEC, we bail + out now. */ + if (!CLASSTYPE_METHOD_VEC (t)) + return; + + for (fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns)) + deduce_noexcept_on_destructor (OVL_CURRENT (fns)); +} + /* Subroutine of set_one_vmethod_tm_attributes. Search base classes of TYPE for virtual functions which FNDECL overrides. Return a mask of the tm attributes found therein. */ @@ -4994,6 +5029,10 @@ check_bases_and_members (tree t) cant_have_const_ctor = 0; no_const_asn_ref = 0; + /* Deduce noexcept on destructors. */ + if (cxx_dialect >= cxx0x) + deduce_noexcept_on_destructors (t); + /* Check all the base-classes. */ check_bases (t, &cant_have_const_ctor, &no_const_asn_ref); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7d986a8..8bca1fa 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4978,6 +4978,7 @@ extern void fixup_attribute_variants (tree); extern tree* decl_cloned_function_p (const_tree, bool); extern void clone_function_decl (tree, int); extern void adjust_clone_args (tree); +extern void deduce_noexcept_on_destructor (tree); /* in cvt.c */ extern tree convert_to_reference (tree, tree, int, int, tree); @@ -5264,6 +5265,8 @@ extern tree get_copy_assign (tree); extern tree get_default_ctor (tree); extern tree get_dtor (tree, tsubst_flags_t); extern tree locate_ctor (tree); +extern tree implicitly_declare_fn (special_function_kind, tree, + bool); /* In optimize.c */ extern bool maybe_clone_body (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a89523d..d210f19 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7448,6 +7448,13 @@ grokfndecl (tree ctype, if (ctype != NULL_TREE) grokclassfn (ctype, decl, flags); + /* 12.4/3 */ + if (cxx_dialect >= cxx0x + && DECL_DESTRUCTOR_P (decl) + && !TYPE_BEING_DEFINED (DECL_CONTEXT (decl)) + && !processing_template_decl) + deduce_noexcept_on_destructor (decl); + decl = check_explicit_specialization (orig_declarator, decl, template_count, 2 * funcdef_flag + diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 0d4793e..79bed4a 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1444,7 +1444,7 @@ explain_implicit_non_constexpr (tree decl) reference argument or a non-const reference. Returns the FUNCTION_DECL for the implicitly declared function. */ -static tree +tree implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) { tree fn; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e2fa4a6..73f22f3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2012-04-01 Paolo Carlini + + PR c++/50043 + * g++.dg/cpp0x/noexcept17.C: New. + * g++.old-deja/g++.eh/cleanup1.C: Adjust. + * g++.dg/tree-ssa/ehcleanup-1.C: Likewise. + * g++.dg/cpp0x/noexcept01.C: Likewise. + * g++.dg/eh/init-temp1.C: Likewise. + * g++.dg/eh/ctor1.C: Likwise. + 2012-03-31 Eric Botcazou * gnat.dg/controlled6.adb: New test. diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept01.C b/gcc/testsuite/g++.dg/cpp0x/noexcept01.C index f314684..b6be1ef 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept01.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept01.C @@ -50,7 +50,7 @@ struct E ~E(); }; -SA (!noexcept (E())); +SA (noexcept (E())); struct F { @@ -74,7 +74,7 @@ void tf() } template void tf(); -template void tf(); +template void tf(); // Make sure that noexcept uses the declared exception-specification, not // any knowledge we might have about whether or not the function really diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept17.C b/gcc/testsuite/g++.dg/cpp0x/noexcept17.C new file mode 100644 index 0000000..82cd844 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept17.C @@ -0,0 +1,54 @@ +// PR c++/50043 +// { dg-options -std=c++11 } + +struct True1 {}; +struct True2 { ~True2(); }; +struct True3 { ~True3(){ throw 0; } }; +struct False { ~False() noexcept(false); }; + +template +struct A : Base +{ +}; + +template +struct B +{ + Member mem; +}; + +template +struct C : Base +{ + Member mem; +}; + +#define SA(X) static_assert(X, #X) + +SA( noexcept(True1())); +SA( noexcept(True2())); +SA( noexcept(True3())); +SA(!noexcept(False())); + +SA( noexcept(A())); +SA( noexcept(A())); +SA( noexcept(A())); +SA(!noexcept(A())); + +SA( noexcept(B())); +SA( noexcept(B())); +SA( noexcept(B())); +SA(!noexcept(B())); + +SA( noexcept(C())); +SA( noexcept(C())); +SA( noexcept(C())); +SA( noexcept(C())); +SA( noexcept(C())); +SA( noexcept(C())); +SA(!noexcept(C())); +SA(!noexcept(C())); +SA(!noexcept(C())); +SA(!noexcept(C())); +SA(!noexcept(C())); +SA(!noexcept(C())); diff --git a/gcc/testsuite/g++.dg/eh/ctor1.C b/gcc/testsuite/g++.dg/eh/ctor1.C index 43b735f..b959d1c 100644 --- a/gcc/testsuite/g++.dg/eh/ctor1.C +++ b/gcc/testsuite/g++.dg/eh/ctor1.C @@ -5,6 +5,12 @@ // PR 411 +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#define NOEXCEPT_FALSE noexcept (false) +#else +#define NOEXCEPT_FALSE +#endif + bool was_f_in_Bar_destroyed=false; struct Foo @@ -17,7 +23,7 @@ struct Foo struct Bar { - ~Bar() + ~Bar() NOEXCEPT_FALSE { throw 1; } diff --git a/gcc/testsuite/g++.dg/eh/init-temp1.C b/gcc/testsuite/g++.dg/eh/init-temp1.C index 529014f..4996cea 100644 --- a/gcc/testsuite/g++.dg/eh/init-temp1.C +++ b/gcc/testsuite/g++.dg/eh/init-temp1.C @@ -1,6 +1,12 @@ // PR c++/15764 // { dg-do run } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#define NOEXCEPT_FALSE noexcept (false) +#else +#define NOEXCEPT_FALSE +#endif + extern "C" void abort (); int thrown; @@ -8,7 +14,7 @@ int thrown; int as; struct a { a () { ++as; } - ~a () { --as; if (thrown++ == 0) throw 42; } + ~a () NOEXCEPT_FALSE { --as; if (thrown++ == 0) throw 42; } }; int f (a const&) { return 1; } diff --git a/gcc/testsuite/g++.dg/tree-ssa/ehcleanup-1.C b/gcc/testsuite/g++.dg/tree-ssa/ehcleanup-1.C index cc492a8..0a29ce9 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/ehcleanup-1.C +++ b/gcc/testsuite/g++.dg/tree-ssa/ehcleanup-1.C @@ -1,9 +1,16 @@ // { dg-options "-O2 -fdump-tree-ehcleanup1-details" } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#define NOEXCEPT_FALSE noexcept (false) +#else +#define NOEXCEPT_FALSE +#endif + extern void can_throw (); class a { public: - ~a () + ~a () NOEXCEPT_FALSE { if (0) can_throw (); diff --git a/gcc/testsuite/g++.old-deja/g++.eh/cleanup1.C b/gcc/testsuite/g++.old-deja/g++.eh/cleanup1.C index 1664643..12f1ec7 100644 --- a/gcc/testsuite/g++.old-deja/g++.eh/cleanup1.C +++ b/gcc/testsuite/g++.old-deja/g++.eh/cleanup1.C @@ -2,6 +2,12 @@ // Bug: obj gets destroyed twice because the fixups for the return are // inside its cleanup region. +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#define NOEXCEPT_FALSE noexcept (false) +#else +#define NOEXCEPT_FALSE +#endif + extern "C" int printf (const char *, ...); int d; @@ -9,7 +15,7 @@ int d; struct myExc { }; struct myExcRaiser { - ~myExcRaiser() { throw myExc(); } + ~myExcRaiser() NOEXCEPT_FALSE { throw myExc(); } }; struct stackObj { -- 2.7.4