[v3] Add std::is_nothrow_destructible, implement LWG 2049

2012-04-23 Thread Paolo Carlini

Hi,

this work from Daniel implements the missing 
std::is_nothrow_destructible trait and implements LWG 2049. Tested 
x86_64-linux, committed to mainline.


Thanks,
Paolo.


2012-04-23  Daniel Krugler  daniel.krueg...@googlemail.com

* include/std/type_traits (is_nothrow_destructible): Implement.
(is_destructible): Implement LWG 2049.
* testsuite/util/testsuite_tr1.h: Add tests.
* testsuite/20_util/is_nothrow_destructible/value.cc: New.
* testsuite/20_util/is_nothrow_destructible/requirements/typedefs.cc:
* testsuite/20_util/is_nothrow_destructible/requirements/
explicit_instantiation.cc: Likewise.
* testsuite/20_util/is_destructible/value.cc: Adjust and extend.
* testsuite/20_util/is_default_constructible/value.cc: Tweak.
* testsuite/20_util/is_constructible/value-2.cc: Likewise.
* testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust
dg-error line numbers.
* testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc:
Likewise.
* testsuite/20_util/declval/requirements/1_neg.cc: Likewise.
Index: include/std/type_traits
===
--- include/std/type_traits (revision 186713)
+++ include/std/type_traits (working copy)
@@ -594,18 +594,14 @@
 : public __and_is_array_Tp, __not_extent_Tp::type
 { };
 
-  // In N3290 is_destructible does not say anything about function 
+  // In N3290 is_destructible does not say anything about function
   // types and abstract types, see LWG 2049. This implementation
-  // describes function types as trivially nothrow destructible and
-  // abstract types as destructible, iff the  explicit destructor
+  // describes function types as non-destructible and all complete
+  // object types as destructible, iff the explicit destructor
   // call expression is wellformed.
-  struct __do_is_destructible_impl_1
+  struct __do_is_destructible_impl
   {
-templatetypename _Up
-  struct __w { _Up __u; };
-
-templatetypename _Tp, typename
- = decltype(declval__w_Tp().~__w_Tp())
+templatetypename _Tp, typename = decltype(declval_Tp().~_Tp())
   static true_type __test(int);
 
 templatetypename
@@ -613,54 +609,85 @@
   };
 
   templatetypename _Tp
-struct __is_destructible_impl_1
-: public __do_is_destructible_impl_1
+struct __is_destructible_impl
+: public __do_is_destructible_impl
 {
   typedef decltype(__test_Tp(0)) type;
 };
 
-  // Special implementation for abstract types
-  struct __do_is_destructible_impl_2
+  templatetypename _Tp,
+   bool = __or_is_void_Tp,
+__is_array_unknown_bounds_Tp,
+is_function_Tp::value,
+   bool = __or_is_reference_Tp, is_scalar_Tp::value
+struct __is_destructible_safe;
+
+  templatetypename _Tp
+struct __is_destructible_safe_Tp, false, false
+: public __is_destructible_impltypename
+   remove_all_extents_Tp::type::type
+{ };
+
+  templatetypename _Tp
+struct __is_destructible_safe_Tp, true, false
+: public false_type { };
+
+  templatetypename _Tp
+struct __is_destructible_safe_Tp, false, true
+: public true_type { };
+
+  /// is_destructible
+  templatetypename _Tp
+struct is_destructible
+: public integral_constantbool, (__is_destructible_safe_Tp::value)
+{ };
+
+  // is_nothrow_destructible requires that is_destructible is
+  // satisfied as well.  We realize that by mimicing the
+  // implementation of is_destructible but refer to noexcept(expr)
+  // instead of decltype(expr).
+  struct __do_is_nt_destructible_impl
   {
-templatetypename _Tp, typename = decltype(declval_Tp().~_Tp())
-  static true_type __test(int);
+templatetypename _Tp
+  static integral_constantbool, noexcept(declval_Tp().~_Tp())
+__test(int);
 
 templatetypename
   static false_type __test(...);
   };
 
   templatetypename _Tp
-struct __is_destructible_impl_2
-: public __do_is_destructible_impl_2
+struct __is_nt_destructible_impl
+: public __do_is_nt_destructible_impl
 {
   typedef decltype(__test_Tp(0)) type;
 };
 
   templatetypename _Tp,
bool = __or_is_void_Tp,
-__is_array_unknown_bounds_Tp::value,
-   bool = __or_is_reference_Tp, is_function_Tp::value
-struct __is_destructible_safe;
+__is_array_unknown_bounds_Tp,
+is_function_Tp::value,
+   bool = __or_is_reference_Tp, is_scalar_Tp::value
+struct __is_nt_destructible_safe;
 
   templatetypename _Tp
-struct __is_destructible_safe_Tp, false, false
-: public conditionalis_abstract_Tp::value,
-__is_destructible_impl_2_Tp,
- __is_destructible_impl_1_Tp::type::type
+struct 

Re: [v3] Add std::is_nothrow_destructible, implement LWG 2049

2012-04-23 Thread Paolo Carlini

On 04/23/2012 11:36 PM, Paolo Carlini wrote:

Hi,

this work from Daniel implements the missing 
std::is_nothrow_destructible trait and implements LWG 2049. Tested 
x86_64-linux, committed to mainline.
Oops. These improvements leads to tidier diagnostics for noexcept15.C 
and I have to adjust it a bit to avoid a spurious regression in the C++ 
testsuite.


Thanks,
Paolo.

//
2012-04-23  Paolo Carlini  paolo.carl...@oracle.com

* g++.dg/cpp0x/noexcept15.C: Adjust for Rev 186726 library changes.
Index: g++.dg/cpp0x/noexcept15.C
===
--- g++.dg/cpp0x/noexcept15.C   (revision 186728)
+++ g++.dg/cpp0x/noexcept15.C   (working copy)
@@ -11,7 +11,7 @@ templateclass Tp
 constexpr single(const Tp e)
 : elem(e) { }   // { dg-error invalid field }
 
-single(single s) // { dg-error not a member }
+single(single s)
 noexcept(std::is_nothrow_move_constructibleTp::value) 
 : elem(s.elem) { } // { dg-error invalid field|no member }
   };