Patchwork [C++] PR 57645 (Core/1123 fallout) 2nd Try

login
register
mail settings
Submitter Paolo Carlini
Date June 27, 2013, 11:05 p.m.
Message ID <51CCC52E.7080900@oracle.com>
Download mbox | patch
Permalink /patch/255242/
State New
Headers show

Comments

Paolo Carlini - June 27, 2013, 11:05 p.m.
Hi,

this is a better fix for this regression, IMHO. Certainly it's simple 
and passes the extended testcase, thus tests for defaulted destructors 
too, etc, with no regressions. The idea, which I got studying in detail 
check_bases_and_members and its comments, is setting temporarily 
TYPE_HAS_NONTRIVIAL_DESTRUCTOR before deducing noexcept on the 
destructors and then restoring it at the end of the work. Makes sense?

Tested x86_64-linux.

Thanks,
Paolo.

///////////////////////////
/cp
2013-06-28  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/57645
	* class.c (deduce_noexcept_on_destructors): Save, set, and restore
	TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) around the main loop over the
	destructors.

/testsuite
2013-06-28  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/57645
	* testsuite/g++.dg/cpp0x/noexcept21.C: New.

Patch

Index: cp/class.c
===================================================================
--- cp/class.c	(revision 200486)
+++ cp/class.c	(working copy)
@@ -4593,15 +4593,18 @@  deduce_noexcept_on_destructor (tree dtor)
 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))
+  bool saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
+  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = true;
+
+  for (tree fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
     deduce_noexcept_on_destructor (OVL_CURRENT (fns));
+
+  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = saved_nontrivial_dtor;
 }
 
 /* Subroutine of set_one_vmethod_tm_attributes.  Search base classes
Index: testsuite/g++.dg/cpp0x/noexcept21.C
===================================================================
--- testsuite/g++.dg/cpp0x/noexcept21.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/noexcept21.C	(working copy)
@@ -0,0 +1,87 @@ 
+// PR c++/57645
+// { dg-do compile { target c++11 } }
+
+struct Thrower
+{
+  ~Thrower() noexcept(false) { throw 1; }
+};
+
+struct ExplicitA
+{
+  ~ExplicitA() {}
+
+  Thrower t;
+};
+
+struct ExplicitB
+{
+  ~ExplicitB();
+
+  Thrower t;
+};
+
+ExplicitB::~ExplicitB() {}
+
+struct ExplicitC
+{
+  ~ExplicitC() = default;
+
+  Thrower t;
+};
+
+struct ExplicitD
+{
+  ~ExplicitD();
+
+  Thrower t;
+};
+
+ExplicitD::~ExplicitD() = default;
+
+struct NoThrower
+{
+  ~NoThrower() noexcept(true) {}
+};
+
+struct ExplicitE
+{
+  ~ExplicitE() {}
+
+  NoThrower t;
+};
+
+struct ExplicitF
+{
+  ~ExplicitF();
+
+  NoThrower t;
+};
+
+ExplicitF::~ExplicitF() {}
+
+struct ExplicitG
+{
+  ~ExplicitG() = default;
+
+  NoThrower t;
+};
+
+struct ExplicitH
+{
+  ~ExplicitH();
+
+  NoThrower t;
+};
+
+ExplicitH::~ExplicitH() = default;
+
+#define SA(X) static_assert(X, #X)
+
+SA( !noexcept(ExplicitA()) );
+SA( !noexcept(ExplicitB()) );
+SA( !noexcept(ExplicitC()) );
+SA( !noexcept(ExplicitD()) );
+SA( noexcept(ExplicitE()) );
+SA( noexcept(ExplicitF()) );
+SA( noexcept(ExplicitG()) );
+SA( noexcept(ExplicitH()) );