Hi,
On 06/28/2013 08:58 PM, Jason Merrill wrote:
On 06/28/2013 12:58 PM, Paolo Carlini wrote:
If you like, this is the rationale behind my last patch: save its
current value, set it only to force a thorough
deduce_noexcept_on_destructor on everything (admittedly, I don't
understand all the details of this), and then restore it, don't fiddle
at this stage with the code we have got setting it to its final value.
Did I explain this well enough?
Yeah, I guess your recent patch is OK; untangling the
interdependencies would be tricky. Just add a comment that you're
setting the flag to avoid early exit from synthesized_method_walk.
Agreed, then. I'm going to commit the below after final testing. It's a
regression, thus in a few days I mean to commit it to the branch too.
Thanks a lot!
Paolo.
/////////////////////////////
Index: cp/class.c
===================================================================
--- cp/class.c (revision 200550)
+++ cp/class.c (working copy)
@@ -4593,15 +4593,20 @@ 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);
+
+ /* Avoid early exit from synthesized_method_walk (c++/57645). */
+ 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,174 @@
+// 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()) );
+// 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()) );