summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-02 00:13:30 +0000
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-02 00:13:30 +0000
commit0568e5f9df00ad1b589a9e4f8b92f714549d663a (patch)
tree112b4c506f1ca661eef5e95c7ff36c47d3577d8d
parent521b90ea0e49b6e24d900021ca02cb701db6a93a (diff)
downloadgcc-0568e5f9df00ad1b589a9e4f8b92f714549d663a.tar.gz
/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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186058 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/class.c39
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/decl.c7
-rw-r--r--gcc/cp/method.c2
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept01.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept17.C54
-rw-r--r--gcc/testsuite/g++.dg/eh/ctor1.C8
-rw-r--r--gcc/testsuite/g++.dg/eh/init-temp1.C8
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/ehcleanup-1.C9
-rw-r--r--gcc/testsuite/g++.old-deja/g++.eh/cleanup1.C8
12 files changed, 156 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7e4e5497e3b..89ea02d1935 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index bc17c82c6a0..7b6559c4231 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 7d986a8cf73..8bca1fa0b63 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 a89523d78f6..d210f199a2d 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 0d4793eb23b..79bed4a053f 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 e2fa4a65282..73f22f3ab4f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept01.C b/gcc/testsuite/g++.dg/cpp0x/noexcept01.C
index f314684eae8..b6be1ef7a3f 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<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
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept17.C b/gcc/testsuite/g++.dg/cpp0x/noexcept17.C
new file mode 100644
index 00000000000..82cd844c067
--- /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 <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>()));
diff --git a/gcc/testsuite/g++.dg/eh/ctor1.C b/gcc/testsuite/g++.dg/eh/ctor1.C
index 43b735f0b00..b959d1c5620 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 529014f497f..4996cea230f 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 cc492a80975..0a29ce9cb4f 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 16646438ed2..12f1ec7a081 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 {