diff mbox

C++ PATCH for core issue 1135 (virtual and exception-specifications with default)

Message ID 4D8CBF85.10509@redhat.com
State New
Headers show

Commit Message

Jason Merrill March 25, 2011, 4:15 p.m. UTC
The resolution of core issue 1135 allows defaulted functions to be 
declared virtual or with an exception specification that matches the one 
on an implicit declaration; this patch implements that.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit c0337ba692c6eadc1d63b96a80b71ac1d59b0e51
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Mar 25 16:04:09 2011 +0100

    	Core 1135
    	* method.c (defaulted_late_check): Check for exception spec mismatch.
    	(defaultable_fn_check): Allow exception spec and virtual.
    	* class.c (check_for_override): A virtual dtor is non-trivial.
diff mbox

Patch

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1325260..adae51f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2474,6 +2474,8 @@  check_for_override (tree decl, tree ctype)
       if (!DECL_VINDEX (decl))
 	DECL_VINDEX (decl) = error_mark_node;
       IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
+      if (DECL_DESTRUCTOR_P (decl))
+	TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype) = true;
     }
 }
 
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 0366988..386a818 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1554,6 +1554,12 @@  defaulted_late_check (tree fn)
   if (DECL_DEFAULTED_IN_CLASS_P (fn))
     {
       tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn));
+      if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))
+	  && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)),
+				 eh_spec, ce_normal))
+	error ("function %q+D defaulted on its first declaration "
+	       "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
@@ -1619,14 +1625,7 @@  defaultable_fn_check (tree fn)
 	    break;
 	  }
       if (TYPE_BEING_DEFINED (DECL_CONTEXT (fn)))
-	{
-	  if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
-	    error ("function %q+D defaulted on its first declaration "
-		   "must not have an exception-specification", fn);
-	  if (DECL_VIRTUAL_P (fn))
-	    error ("%qD declared virtual cannot be defaulted in the class "
-		   "body", fn);
-	}
+	/* Defer checking.  */;
       else if (!processing_template_decl)
 	defaulted_late_check (fn);
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted15.C b/gcc/testsuite/g++.dg/cpp0x/defaulted15.C
index 4c5b11c..0a47c20 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted15.C
@@ -54,5 +54,5 @@  struct G: public F
 
 struct H
 {
-  virtual ~H() = default;	// { dg-error "declared virtual" }
+  virtual ~H() = default;
 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted22.C b/gcc/testsuite/g++.dg/cpp0x/defaulted22.C
new file mode 100644
index 0000000..61e9d32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted22.C
@@ -0,0 +1,23 @@ 
+// Test that a virtual defaulted constructor is still virtual.
+// { dg-do run }
+// { dg-options -std=c++0x }
+
+int r = 1;
+
+struct A
+{
+  virtual ~A() = default;
+};
+
+struct B: A
+{
+  ~B() noexcept { r = 0; }
+};
+
+A* ap = new B();
+
+int main()
+{
+  delete ap;
+  return r;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted23.C b/gcc/testsuite/g++.dg/cpp0x/defaulted23.C
new file mode 100644
index 0000000..5b4438d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted23.C
@@ -0,0 +1,27 @@ 
+// Test for checking of exception specifications on defaulted fns
+// { dg-options -std=c++0x }
+
+struct A
+{
+  A() noexcept = default;
+};
+
+struct B
+{
+  B() throw (int) = default; // { dg-error "exception-specification that differs from the implicit declaration" }
+};
+
+struct C
+{
+  C() throw (int) { }
+};
+
+struct D: C
+{
+  D() throw (int) = default;
+};
+
+struct E
+{
+  E() = default;
+};