Hi,

On 06/28/2013 02:52 AM, Jason Merrill wrote:
On 06/19/2013 08:22 PM, Paolo Carlini wrote:
If, in check_bases_and_members, I simply move
deduce_noexcept_on_destructors after check_methods and nothing else, all
the new testcases are fine + the tests added for Core/1123, but there
are regressions, for example for testcases involving virtual
destructors, eg, debug/dwarf2/non-virtual-thunk.C.

Probably because we need to update the exception specification before we check for overrides, since that check will look at the exception specification.

Let's move

      if (DECL_DESTRUCTOR_P (x) && user_provided_p (x))
        TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1;

to the top of the loop in check_methods, and call deduce_noexcept_on_destructor under the same if.
Thanks. If I do that, noexcept21.C is fine but there are regressions, of the same kind, for two testcases which by now I know well: cpp0x/defaulted33.C and defaulted38.C. For example:

defaulted33.C: In instantiation of ‘class ArrayNHD<int, 1u>’:
defaulted33.C:31:10:   required from here
defaulted33.C:22:3: error: looser throw specifier for ‘ArrayNHD<T, N>::~ArrayNHD() [with T = int; unsigned int N = 1u]’
   ~ArrayNHD() = default;
   ^
defaulted33.C:15:7: error: overriding ‘virtual IOHD::~IOHD() noexcept (true)’
 class IOHD : public InputHD, public OutputHD
       ^

Note that check_for_override itself does set TYPE_HAS_NONTRIVIAL_DESTRUCTOR, when it sees virtual destructors. If I hack the if above to something like:

          if (DECL_DESTRUCTOR_P (x)
             && (user_provided_p (x) || DECL_VIRTUAL_P (x))
              TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1;

then defaulted38.C doesn't regress anymore. However defaulted33.C still fails, it has a base class with a virtual destructor but then the derived class has simply ~ArrayNHD() = default; Should we detect this latter case too?

Finally, I must admit that I'm a little confused about the real meaning of TYPE_HAS_NONTRIVIAL_DESTRUCTOR, which is also the very predicate that we use for the semantics of __has_trivial_destructor. It looks like that in some cases we *cannot* set it to its final value *before* having called deduce_noexcept_on_destructor. Consider:

#define SA(X) static_assert ((X), #X)

struct Thrower
{
  ~Thrower() noexcept(false);
};

struct C
{
  // Thrower t;

  ~C() = default;
};

SA(__has_trivial_destructor(C));

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?

Thanks,
Paolo.



Reply via email to