Patchwork [C++] PR 53903

login
register
mail settings
Submitter Paolo Carlini
Date May 14, 2013, 10:45 a.m.
Message ID <519215D3.3060507@oracle.com>
Download mbox | patch
Permalink /patch/243667/
State New
Headers show

Comments

Paolo Carlini - May 14, 2013, 10:45 a.m.
Hi,

in this PR Jonathan noticed that we don't enforce the first part of 
8.4.2/2, about compatibility of the exception-specification of defaulted 
functions in general, not the special case of those defaulted on the 
first declaration. Extending the existing check beyond  
DECL_DEFAULTED_IN_CLASS_P (fn) seems easy, the below passes testing on 
x86_64-linux.

Thanks,
Paolo.

////////////////////////
/cp
2013-05-14  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/53903
	* method.c (defaulted_late_check): Check for compatible exception
	specification out of class explicitly defaulted functions too.

/testsuite
2013-05-14  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/53903
	* g++.dg/cpp0x/defaulted43.C: New.
Jason Merrill - May 14, 2013, 12:43 p.m.
OK.

Jason

Patch

Index: cp/method.c
===================================================================
--- cp/method.c	(revision 198863)
+++ cp/method.c	(working copy)
@@ -1755,6 +1755,7 @@  defaulted_late_check (tree fn)
   bool fn_const_p = (copy_fn_p (fn) == 2);
   tree implicit_fn = implicitly_declare_fn (kind, ctx, fn_const_p,
 					    NULL, NULL);
+  tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn));
 
   if (!same_type_p (TREE_TYPE (TREE_TYPE (fn)),
 		    TREE_TYPE (TREE_TYPE (implicit_fn)))
@@ -1766,33 +1767,42 @@  defaulted_late_check (tree fn)
 		"does not match expected signature %qD", implicit_fn);
     }
 
-  /* 8.4.2/2: If it is explicitly defaulted on its first declaration, it is
+  /* 8.4.2/2: An explicitly-defaulted function (...) may have an explicit
+     exception-specification only if it is compatible (15.4) with the 
+     exception-specification on the implicit declaration.  If a function
+     is explicitly defaulted on its first declaration, (...) it is
      implicitly considered to have the same exception-specification as if
      it had been implicitly declared.  */
-  if (DECL_DEFAULTED_IN_CLASS_P (fn))
+  if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
     {
-      tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn));
-      if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
+      maybe_instantiate_noexcept (fn);
+      if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)),
+			      eh_spec, ce_normal))
 	{
-	  maybe_instantiate_noexcept (fn);
-	  if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)),
-				  eh_spec, ce_normal))
+	  if (DECL_DEFAULTED_IN_CLASS_P (fn))
 	    error ("function %q+D defaulted on its first declaration "
 		   "with an exception-specification that differs from "
 		   "the implicit declaration %q#D", fn, implicit_fn);
+	  else
+	    error ("function %q+D defaulted on its redeclaration "
+		   "with an exception-specification that differs from "
+		   "the implicit declaration %q#D", fn, implicit_fn);
 	}
-      TREE_TYPE (fn) = build_exception_variant (TREE_TYPE (fn), eh_spec);
-      if (DECL_DECLARED_CONSTEXPR_P (implicit_fn))
-	{
-	  /* Hmm...should we do this for out-of-class too? Should it be OK to
-	     add constexpr later like inline, rather than requiring
-	     declarations to match?  */
-	  DECL_DECLARED_CONSTEXPR_P (fn) = true;
-	  if (kind == sfk_constructor)
-	    TYPE_HAS_CONSTEXPR_CTOR (ctx) = true;
-	}
     }
+  if (DECL_DEFAULTED_IN_CLASS_P (fn))
+    TREE_TYPE (fn) = build_exception_variant (TREE_TYPE (fn), eh_spec);
 
+  if (DECL_DEFAULTED_IN_CLASS_P (fn)
+      && DECL_DECLARED_CONSTEXPR_P (implicit_fn))
+    {
+      /* Hmm...should we do this for out-of-class too? Should it be OK to
+	 add constexpr later like inline, rather than requiring
+	 declarations to match?  */
+      DECL_DECLARED_CONSTEXPR_P (fn) = true;
+      if (kind == sfk_constructor)
+	TYPE_HAS_CONSTEXPR_CTOR (ctx) = true;
+    }
+
   if (!DECL_DECLARED_CONSTEXPR_P (implicit_fn)
       && DECL_DECLARED_CONSTEXPR_P (fn))
     {
Index: testsuite/g++.dg/cpp0x/defaulted43.C
===================================================================
--- testsuite/g++.dg/cpp0x/defaulted43.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/defaulted43.C	(working copy)
@@ -0,0 +1,50 @@ 
+// PR c++/53903
+// { dg-do compile { target c++11 } }
+
+struct T
+{
+  T() noexcept(false) { }
+  ~T() noexcept(false) { }
+};
+
+struct A
+{
+  A() noexcept;
+  ~A() noexcept;
+
+  T t;
+};
+
+A::A() noexcept = default;   // { dg-error "defaulted" }
+A::~A() noexcept = default;  // { dg-error "defaulted" }
+
+struct U
+{
+  U() noexcept(false) { }
+  ~U() noexcept(false) { }
+};
+
+struct B
+{
+  B() noexcept(false);
+  ~B() noexcept(false);
+
+  U u;
+};
+
+B::B() noexcept(false) = default;
+B::~B() noexcept(false) = default;
+
+struct V
+{
+  V() noexcept(false) { }
+  ~V() noexcept(false) { }
+};
+
+struct C
+{
+  C() noexcept = default;     // { dg-error "defaulted" }
+  ~C() noexcept = default;    // { dg-error "defaulted" }
+
+  V v;
+};