Hi again,

On 03/26/2012 09:31 PM, Jason Merrill wrote:
On 03/26/2012 07:22 AM, Paolo Carlini wrote:
My basic idea so far is very simple:

--- class.c (revision 185792)
+++ class.c (working copy)
@@ -1001,6 +1001,10 @@ add_method (tree type, tree method, tree using_dec
"destructor",
type);
}
+ else if (cxx_dialect >= cxx0x
+ && !TYPE_RAISES_EXCEPTIONS (TREE_TYPE (method)))
+ TREE_TYPE (method) = build_exception_variant (TREE_TYPE (method),
+ noexcept_true_spec);
}

That would implement N1366, but implementing N3204 is a bit more involved. You need to copy TYPE_RAISES_EXCEPTIONS from the result of implicitly_declare_fn; see defaulted_late_check for something similar.

Also, this is too early, since we can't know what the eh specification of the implicit declaration would be until the closing brace of the class.
I think I understand your explanation and the below appears already to work pretty well. Is it on the right track? What about the check_redeclaration_exception_specification bits?

Thanks in advance for any further feedback,
Paolo.

////////////////////////
Index: class.c
===================================================================
--- class.c     (revision 185911)
+++ class.c     (working copy)
@@ -4321,6 +4321,37 @@ clone_constructors_and_destructors (tree t)
     clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
 }
 
+/* For each destructor in T, deduce noexcept per:
+
+   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))
+    {
+      tree fn = OVL_CURRENT (fns);
+      if (!TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
+       {
+         tree ctx = DECL_CONTEXT (fn);
+         tree implicit_fn = implicitly_declare_fn (sfk_destructor, ctx,
+                                                   /*const_p=*/false);
+         tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn));
+
+         TREE_TYPE (fn) = build_exception_variant (TREE_TYPE (fn), eh_spec);
+       }
+    }
+}
+
 /* 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.  */
@@ -5129,6 +5160,10 @@ check_bases_and_members (tree t)
      do anything with non-static member functions.  */
   finalize_literal_type_property (t);
 
+  /* Deduce noexcept.  */
+  if (cxx_dialect >= cxx0x)
+    deduce_noexcept_on_destructors (t);
+
   /* Create the in-charge and not-in-charge variants of constructors
      and destructors.  */
   clone_constructors_and_destructors (t);
Index: decl.c
===================================================================
--- decl.c      (revision 185911)
+++ decl.c      (working copy)
@@ -1144,7 +1144,13 @@ check_redeclaration_exception_specification (tree
   if ((pedantic || ! DECL_IN_SYSTEM_HEADER (old_decl))
       && ! DECL_IS_BUILTIN (old_decl)
       && flag_exceptions
-      && !comp_except_specs (new_exceptions, old_exceptions, ce_normal))
+      && !comp_except_specs (new_exceptions, old_exceptions, ce_normal)
+      /* Special case in C++11: noexcept has been deduced as true for
+        the declaration and there is no exception-specification on the
+        definition.  */
+      && !(DECL_DESTRUCTOR_P (new_decl)
+          && cxx_dialect >= cxx0x
+          && !new_exceptions && TYPE_NOEXCEPT_P (old_type)))
     {
       error ("declaration of %qF has a different exception specifier",
             new_decl);
Index: method.c
===================================================================
--- method.c    (revision 185911)
+++ method.c    (working copy)
@@ -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: cp-tree.h
===================================================================
--- cp-tree.h   (revision 185911)
+++ cp-tree.h   (working copy)
@@ -5264,6 +5264,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);

Reply via email to