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
This commit is contained in:
parent
ea2c1a6d67
commit
593a083530
12 changed files with 156 additions and 7 deletions
|
@ -1,3 +1,14 @@
|
|||
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>
|
||||
|
||||
PR c++/52718
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 +
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
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>
|
||||
|
||||
* gnat.dg/controlled6.adb: New test.
|
||||
|
|
|
@ -50,7 +50,7 @@ struct E
|
|||
~E();
|
||||
};
|
||||
|
||||
SA (!noexcept (E()));
|
||||
SA (noexcept (E()));
|
||||
|
||||
struct F
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ void tf()
|
|||
}
|
||||
|
||||
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
|
||||
// any knowledge we might have about whether or not the function really
|
||||
|
|
54
gcc/testsuite/g++.dg/cpp0x/noexcept17.C
Normal file
54
gcc/testsuite/g++.dg/cpp0x/noexcept17.C
Normal file
|
@ -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 <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 @@
|
|||
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue