re PR c++/50043 ([C++0x] Implement core/1123)
authorPaolo Carlini <paolo.carlini@oracle.com>
Mon, 2 Apr 2012 00:13:30 +0000 (00:13 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Mon, 2 Apr 2012 00:13:30 +0000 (00:13 +0000)
/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

12 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/method.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/noexcept01.C
gcc/testsuite/g++.dg/cpp0x/noexcept17.C [new file with mode: 0644]
gcc/testsuite/g++.dg/eh/ctor1.C
gcc/testsuite/g++.dg/eh/init-temp1.C
gcc/testsuite/g++.dg/tree-ssa/ehcleanup-1.C
gcc/testsuite/g++.old-deja/g++.eh/cleanup1.C

index 7e4e549..89ea02d 100644 (file)
@@ -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
index bc17c82..7b6559c 100644 (file)
@@ -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);
index 7d986a8..8bca1fa 100644 (file)
@@ -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);
index a89523d..d210f19 100644 (file)
@@ -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 +
index 0d4793e..79bed4a 100644 (file)
@@ -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;
index e2fa4a6..73f22f3 100644 (file)
@@ -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.
index f314684..b6be1ef 100644 (file)
@@ -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 (file)
index 0000000..82cd844
--- /dev/null
@@ -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>()));
index 43b735f..b959d1c 100644 (file)
@@ -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;
   }
index 529014f..4996cea 100644 (file)
@@ -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; } 
index cc492a8..0a29ce9 100644 (file)
@@ -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 ();
index 1664643..12f1ec7 100644 (file)
@@ -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 {