Commit 593a0835 by Paolo Carlini Committed by Paolo Carlini

re PR c++/50043 ([C++0x] Implement core/1123)

/cp
2012-04-01  Paolo Carlini  <paolo.carlini@oracle.com>

	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  <paolo.carlini@oracle.com>

	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
parent ea2c1a6d
2012-04-01 Paolo Carlini <paolo.carlini@oracle.com>
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 <paolo.carlini@oracle.com> 2012-03-29 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/52718 PR c++/52718
......
...@@ -4321,6 +4321,41 @@ clone_constructors_and_destructors (tree t) ...@@ -4321,6 +4321,41 @@ clone_constructors_and_destructors (tree t)
clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1); 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 /* Subroutine of set_one_vmethod_tm_attributes. Search base classes
of TYPE for virtual functions which FNDECL overrides. Return a of TYPE for virtual functions which FNDECL overrides. Return a
mask of the tm attributes found therein. */ mask of the tm attributes found therein. */
...@@ -4994,6 +5029,10 @@ check_bases_and_members (tree t) ...@@ -4994,6 +5029,10 @@ check_bases_and_members (tree t)
cant_have_const_ctor = 0; cant_have_const_ctor = 0;
no_const_asn_ref = 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 all the base-classes. */
check_bases (t, &cant_have_const_ctor, check_bases (t, &cant_have_const_ctor,
&no_const_asn_ref); &no_const_asn_ref);
......
...@@ -4978,6 +4978,7 @@ extern void fixup_attribute_variants (tree); ...@@ -4978,6 +4978,7 @@ extern void fixup_attribute_variants (tree);
extern tree* decl_cloned_function_p (const_tree, bool); extern tree* decl_cloned_function_p (const_tree, bool);
extern void clone_function_decl (tree, int); extern void clone_function_decl (tree, int);
extern void adjust_clone_args (tree); extern void adjust_clone_args (tree);
extern void deduce_noexcept_on_destructor (tree);
/* in cvt.c */ /* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree); extern tree convert_to_reference (tree, tree, int, int, tree);
...@@ -5264,6 +5265,8 @@ extern tree get_copy_assign (tree); ...@@ -5264,6 +5265,8 @@ extern tree get_copy_assign (tree);
extern tree get_default_ctor (tree); extern tree get_default_ctor (tree);
extern tree get_dtor (tree, tsubst_flags_t); extern tree get_dtor (tree, tsubst_flags_t);
extern tree locate_ctor (tree); extern tree locate_ctor (tree);
extern tree implicitly_declare_fn (special_function_kind, tree,
bool);
/* In optimize.c */ /* In optimize.c */
extern bool maybe_clone_body (tree); extern bool maybe_clone_body (tree);
......
...@@ -7448,6 +7448,13 @@ grokfndecl (tree ctype, ...@@ -7448,6 +7448,13 @@ grokfndecl (tree ctype,
if (ctype != NULL_TREE) if (ctype != NULL_TREE)
grokclassfn (ctype, decl, flags); 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, decl = check_explicit_specialization (orig_declarator, decl,
template_count, template_count,
2 * funcdef_flag + 2 * funcdef_flag +
......
...@@ -1444,7 +1444,7 @@ explain_implicit_non_constexpr (tree decl) ...@@ -1444,7 +1444,7 @@ explain_implicit_non_constexpr (tree decl)
reference argument or a non-const reference. Returns the reference argument or a non-const reference. Returns the
FUNCTION_DECL for the implicitly declared function. */ FUNCTION_DECL for the implicitly declared function. */
static tree tree
implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
{ {
tree fn; tree fn;
......
2012-04-01 Paolo Carlini <paolo.carlini@oracle.com>
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 <ebotcazou@adacore.com> 2012-03-31 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/controlled6.adb: New test. * gnat.dg/controlled6.adb: New test.
......
...@@ -50,7 +50,7 @@ struct E ...@@ -50,7 +50,7 @@ struct E
~E(); ~E();
}; };
SA (!noexcept (E())); SA (noexcept (E()));
struct F struct F
{ {
...@@ -74,7 +74,7 @@ void tf() ...@@ -74,7 +74,7 @@ void tf()
} }
template void tf<int,true>(); template void tf<int,true>();
template void tf<E, false>(); template void tf<E, true>();
// Make sure that noexcept uses the declared exception-specification, not // Make sure that noexcept uses the declared exception-specification, not
// any knowledge we might have about whether or not the function really // any knowledge we might have about whether or not the function really
......
// PR c++/50043
// { dg-options -std=c++11 }
struct True1 {};
struct True2 { ~True2(); };
struct True3 { ~True3(){ throw 0; } };
struct False { ~False() noexcept(false); };
template <typename Base>
struct A : Base
{
};
template <typename Member>
struct B
{
Member mem;
};
template <typename Base, typename Member>
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<True1>()));
SA( noexcept(A<True2>()));
SA( noexcept(A<True3>()));
SA(!noexcept(A<False>()));
SA( noexcept(B<True1>()));
SA( noexcept(B<True2>()));
SA( noexcept(B<True3>()));
SA(!noexcept(B<False>()));
SA( noexcept(C<True1, True2>()));
SA( noexcept(C<True1, True3>()));
SA( noexcept(C<True2, True3>()));
SA( noexcept(C<True2, True1>()));
SA( noexcept(C<True3, True1>()));
SA( noexcept(C<True3, True2>()));
SA(!noexcept(C<False, True1>()));
SA(!noexcept(C<False, True2>()));
SA(!noexcept(C<False, True3>()));
SA(!noexcept(C<True1, False>()));
SA(!noexcept(C<True2, False>()));
SA(!noexcept(C<True3, False>()));
...@@ -5,6 +5,12 @@ ...@@ -5,6 +5,12 @@
// PR 411 // PR 411
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define NOEXCEPT_FALSE noexcept (false)
#else
#define NOEXCEPT_FALSE
#endif
bool was_f_in_Bar_destroyed=false; bool was_f_in_Bar_destroyed=false;
struct Foo struct Foo
...@@ -17,7 +23,7 @@ struct Foo ...@@ -17,7 +23,7 @@ struct Foo
struct Bar struct Bar
{ {
~Bar() ~Bar() NOEXCEPT_FALSE
{ {
throw 1; throw 1;
} }
......
// PR c++/15764 // PR c++/15764
// { dg-do run } // { dg-do run }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define NOEXCEPT_FALSE noexcept (false)
#else
#define NOEXCEPT_FALSE
#endif
extern "C" void abort (); extern "C" void abort ();
int thrown; int thrown;
...@@ -8,7 +14,7 @@ int thrown; ...@@ -8,7 +14,7 @@ int thrown;
int as; int as;
struct a { struct a {
a () { ++as; } a () { ++as; }
~a () { --as; if (thrown++ == 0) throw 42; } ~a () NOEXCEPT_FALSE { --as; if (thrown++ == 0) throw 42; }
}; };
int f (a const&) { return 1; } int f (a const&) { return 1; }
......
// { dg-options "-O2 -fdump-tree-ehcleanup1-details" } // { 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 (); extern void can_throw ();
class a class a
{ {
public: public:
~a () ~a () NOEXCEPT_FALSE
{ {
if (0) if (0)
can_throw (); can_throw ();
......
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
// Bug: obj gets destroyed twice because the fixups for the return are // Bug: obj gets destroyed twice because the fixups for the return are
// inside its cleanup region. // inside its cleanup region.
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define NOEXCEPT_FALSE noexcept (false)
#else
#define NOEXCEPT_FALSE
#endif
extern "C" int printf (const char *, ...); extern "C" int printf (const char *, ...);
int d; int d;
...@@ -9,7 +15,7 @@ int d; ...@@ -9,7 +15,7 @@ int d;
struct myExc { }; struct myExc { };
struct myExcRaiser { struct myExcRaiser {
~myExcRaiser() { throw myExc(); } ~myExcRaiser() NOEXCEPT_FALSE { throw myExc(); }
}; };
struct stackObj { struct stackObj {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment