]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Implement new C++ intrinsics __is_assignable and __is_constructible.
authorVille Voutilainen <ville.voutilainen@gmail.com>
Wed, 17 May 2017 13:54:23 +0000 (16:54 +0300)
committerVille Voutilainen <ville@gcc.gnu.org>
Wed, 17 May 2017 13:54:23 +0000 (16:54 +0300)
c-family/

Implement new C++ intrinsics __is_assignable and __is_constructible.
* c-common.c (__is_assignable, __is_constructible): New.
* c-common.h (RID_IS_ASSIGNABLE, RID_IS_CONSTRUCTIBLE): Likewise.

cp/

PR c++/80654
PR c++/80682
Implement new C++ intrinsics __is_assignable and __is_constructible.
* cp-tree.h (CPTK_IS_ASSIGNABLE, CPTK_IS_CONSTRUCTIBLE): New.
(is_xible): New.
* cxx-pretty-print.c (pp_cxx_trait_expression): Handle
CPTK_IS_ASSIGNABLE and CPTK_IS_CONSTRUCTIBLE.
* method.c (constructible_expr): Set cp_unevaluated.
(is_xible_helper): New.
(is_trivially_xible): Adjust.
(is_xible): New.
* parser.c (cp_parser_primary_expression): Handle
RID_IS_ASSIGNABLE and RID_IS_CONSTRUCTIBLE.
(cp_parser_trait_expr): Likewise.
* semantics.c (trait_expr_value): Handle
CPTK_IS_ASSIGNABLE and CPTK_IS_CONSTRUCTIBLE.

testsuite/

* g++.dg/ext/80654.C: New.

libstdc++-v3/

Implement new C++ intrinsics __is_assignable and __is_constructible.
* include/std/type_traits (__do_is_static_castable_impl): Remove.
(__is_static_castable_impl, __is_static_castable_safe): Likewise.
(__is_static_castable, __do_is_direct_constructible_impl): Likewise.
(__is_direct_constructible_impl): Likewise.
(__is_direct_constructible_new_safe): Likewise.
(__is_base_to_derived_ref, __is_lvalue_to_rvalue_ref): Likewise.
(__is_direct_constructible_ref_cast): Likewise.
(__is_direct_constructible_new, __is_direct_constructible): Likewise.
(__do_is_nary_constructible_impl): Likewise.
(__is_nary_constructible_impl, __is_nary_constructible): Likewise.
(__is_constructible_impl): Likewise.
(is_constructible): Call the intrinsic.
(__is_assignable_helper): Remove.
(is_assignable): Call the intrinsic.
(is_trivially_constructible): Likewise.
(__is_trivially_copy_constructible_impl): New.
(is_trivially_copy_constructible): Use it.
(__is_trivially_move_constructible_impl): New.
(is_trivially_move_constructible): Use it.
(is_trivially_assignable): Call the intrinsic.
(__is_trivially_copy_assignable_impl): New.
(is_trivially_copy_assignable): Use it.
(__is_trivially_move_assignable_impl): New.
(is_trivially_move_assignable): Use it.
(testsuite/20_util/declval/requirements/1_neg.cc): Adjust.
(testsuite/20_util/is_trivially_copy_assignable/value.cc):
Add test for void.
(testsuite/20_util/is_trivially_copy_constructible/value.cc): Likewise.
(testsuite/20_util/is_trivially_move_assignable/value.cc): Likewise.
(testsuite/20_util/is_trivially_move_constructible/value.cc): Likewise.
(testsuite/20_util/make_signed/requirements/typedefs_neg.cc): Adjust.
(testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc):
Likewise.

From-SVN: r248153

19 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/cxx-pretty-print.c
gcc/cp/method.c
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/ext/80654.C [new file with mode: 0644]
libstdc++-v3/ChangeLog
libstdc++-v3/include/std/type_traits
libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
libstdc++-v3/testsuite/20_util/is_trivially_copy_assignable/value.cc
libstdc++-v3/testsuite/20_util/is_trivially_copy_constructible/value.cc
libstdc++-v3/testsuite/20_util/is_trivially_move_assignable/value.cc
libstdc++-v3/testsuite/20_util/is_trivially_move_constructible/value.cc
libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc

index 4b1c226da8131f170a6100d4db568239d54987b0..428d733da1a318d9b502f081d350df36512da2f6 100644 (file)
@@ -1,3 +1,9 @@
+2017-05-17  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Implement new C++ intrinsics __is_assignable and __is_constructible.
+       * c-common.c (__is_assignable, __is_constructible): New.
+       * c-common.h (RID_IS_ASSIGNABLE, RID_IS_CONSTRUCTIBLE): Likewise.
+
 2017-05-17  Martin Liska  <mliska@suse.cz>
 
        * c-common.h: Introduce dump_flags_t type and
index f606e948ae51294cad5658f67a5719c8da091300..a3c63d74d00f2cd219f74b10922c80f1c17f148d 100644 (file)
@@ -514,6 +514,8 @@ const struct c_common_resword c_common_reswords[] =
   { "volatile",                RID_VOLATILE,   0 },
   { "wchar_t",         RID_WCHAR,      D_CXXONLY },
   { "while",           RID_WHILE,      0 },
+  { "__is_assignable", RID_IS_ASSIGNABLE, D_CXXONLY },
+  { "__is_constructible", RID_IS_CONSTRUCTIBLE, D_CXXONLY },
 
   /* C++ transactional memory.  */
   { "synchronized",    RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM },
index 5ce3b458af3da49802707f28ea2c2848dc4acd11..3023b07af67349d1e3e647c15d356d14df44f80c 100644 (file)
@@ -172,6 +172,7 @@ enum rid
   RID_IS_TRIVIALLY_ASSIGNABLE, RID_IS_TRIVIALLY_CONSTRUCTIBLE,
   RID_IS_TRIVIALLY_COPYABLE,
   RID_IS_UNION,                RID_UNDERLYING_TYPE,
+  RID_IS_ASSIGNABLE,           RID_IS_CONSTRUCTIBLE,
 
   /* C++11 */
   RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
index 7136b5d8946e4c18bc4f751f9d0d9be8c07c7e6f..f657194f419e637c4e3961f9ef853181c160e836 100644 (file)
@@ -1,3 +1,22 @@
+2017-05-17  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       PR c++/80654
+       PR c++/80682
+       Implement new C++ intrinsics __is_assignable and __is_constructible.
+       * cp-tree.h (CPTK_IS_ASSIGNABLE, CPTK_IS_CONSTRUCTIBLE): New.
+       (is_xible): New.
+       * cxx-pretty-print.c (pp_cxx_trait_expression): Handle
+       CPTK_IS_ASSIGNABLE and CPTK_IS_CONSTRUCTIBLE.
+       * method.c (constructible_expr): Set cp_unevaluated.
+       (is_xible_helper): New.
+       (is_trivially_xible): Adjust.
+       (is_xible): New.
+       * parser.c (cp_parser_primary_expression): Handle
+       RID_IS_ASSIGNABLE and RID_IS_CONSTRUCTIBLE.
+       (cp_parser_trait_expr): Likewise.
+       * semantics.c (trait_expr_value): Handle
+       CPTK_IS_ASSIGNABLE and CPTK_IS_CONSTRUCTIBLE.
+
 2017-05-17  Nathan Sidwell  <nathan@acm.org>
 
        * cp-tree.h (ovl_iterator::using_p): New predicate.
index 942ac6195b6df694c116a2de6fa4a0b101711c23..921118635a68243009f069ef0297eb531c9b05f9 100644 (file)
@@ -1016,7 +1016,9 @@ enum cp_trait_kind
   CPTK_IS_TRIVIALLY_CONSTRUCTIBLE,
   CPTK_IS_TRIVIALLY_COPYABLE,
   CPTK_IS_UNION,
-  CPTK_UNDERLYING_TYPE
+  CPTK_UNDERLYING_TYPE,
+  CPTK_IS_ASSIGNABLE,
+  CPTK_IS_CONSTRUCTIBLE
 };
 
 /* The types that we are processing.  */
@@ -6227,6 +6229,7 @@ extern void use_thunk                             (tree, bool);
 extern bool trivial_fn_p                       (tree);
 extern tree forward_parm                       (tree);
 extern bool is_trivially_xible                 (enum tree_code, tree, tree);
+extern bool is_xible                           (enum tree_code, tree, tree);
 extern tree get_defaulted_eh_spec              (tree);
 extern tree unevaluated_noexcept_spec          (void);
 extern void after_nsdmi_defaulted_late_checks   (tree);
index e92a72af12924b77306f1f76c28a17355d60e5b2..b74a56f42000ef474d4c37b28718ba88c5ec44df 100644 (file)
@@ -2634,6 +2634,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
     case CPTK_IS_LITERAL_TYPE:
       pp_cxx_ws_string (pp, "__is_literal_type");
       break;
+    case CPTK_IS_ASSIGNABLE:
+      pp_cxx_ws_string (pp, "__is_assignable");
+      break;
+    case CPTK_IS_CONSTRUCTIBLE:
+      pp_cxx_ws_string (pp, "__is_constructible");
+      break;
 
     default:
       gcc_unreachable ();
index 9898ff19089723bb1f3c5139a76c8bbc584c9135..756b59dc354b0b7a044635fee6218903f7c713ee 100644 (file)
@@ -1162,6 +1162,7 @@ constructible_expr (tree to, tree from)
     {
       tree ctype = to;
       vec<tree, va_gc> *args = NULL;
+      cp_unevaluated cp_uneval_guard;
       if (TREE_CODE (to) != REFERENCE_TYPE)
        to = cp_build_reference_type (to, /*rval*/false);
       tree ob = build_stub_object (to);
@@ -1198,22 +1199,36 @@ constructible_expr (tree to, tree from)
   return expr;
 }
 
-/* Returns true iff TO is trivially assignable (if CODE is MODIFY_EXPR) or
+/* Returns a tree iff TO is assignable (if CODE is MODIFY_EXPR) or
    constructible (otherwise) from FROM, which is a single type for
    assignment or a list of types for construction.  */
 
-bool
-is_trivially_xible (enum tree_code code, tree to, tree from)
+static tree
+is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
 {
-  if (VOID_TYPE_P (to))
-    return false;
+  if (VOID_TYPE_P (to) || ABSTRACT_CLASS_TYPE_P (to)
+      || (from && FUNC_OR_METHOD_TYPE_P (from)
+         && (TYPE_READONLY (from) || FUNCTION_REF_QUALIFIED (from))))
+    return error_mark_node;
   tree expr;
   if (code == MODIFY_EXPR)
     expr = assignable_expr (to, from);
-  else if (from && TREE_CHAIN (from))
-    return false; // only 0- and 1-argument ctors can be trivial
+  else if (trivial && from && TREE_CHAIN (from))
+    return error_mark_node; // only 0- and 1-argument ctors can be trivial
   else
     expr = constructible_expr (to, from);
+  return expr;
+}
+
+/* Returns true iff TO is trivially assignable (if CODE is MODIFY_EXPR) or
+   constructible (otherwise) from FROM, which is a single type for
+   assignment or a list of types for construction.  */
+
+bool
+is_trivially_xible (enum tree_code code, tree to, tree from)
+{
+  tree expr;
+  expr = is_xible_helper (code, to, from, /*trivial*/true);
 
   if (expr == error_mark_node)
     return false;
@@ -1221,6 +1236,19 @@ is_trivially_xible (enum tree_code code, tree to, tree from)
   return !nt;
 }
 
+/* Returns true iff TO is assignable (if CODE is MODIFY_EXPR) or
+   constructible (otherwise) from FROM, which is a single type for
+   assignment or a list of types for construction.  */
+
+bool
+is_xible (enum tree_code code, tree to, tree from)
+{
+  tree expr = is_xible_helper (code, to, from, /*trivial*/false);
+  if (expr == error_mark_node)
+    return false;
+  return !!expr;
+}
+
 /* Subroutine of synthesized_method_walk.  Update SPEC_P, TRIVIAL_P and
    DELETED_P or give an error message MSG with argument ARG.  */
 
index 7ba20752b6a6282370f0492b7a14745595a3ed0f..7a87a5e623d55eecbb7c371fdf0d8f0736945531 100644 (file)
@@ -5135,6 +5135,8 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_IS_TRIVIALLY_CONSTRUCTIBLE:
        case RID_IS_TRIVIALLY_COPYABLE:
        case RID_IS_UNION:
+       case RID_IS_ASSIGNABLE:
+       case RID_IS_CONSTRUCTIBLE:
          return cp_parser_trait_expr (parser, token->keyword);
 
        // C++ concepts
@@ -9686,6 +9688,14 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_DIRECT_BASES:
       kind = CPTK_DIRECT_BASES;
       break;
+    case RID_IS_ASSIGNABLE:
+      kind = CPTK_IS_ASSIGNABLE;
+      binary = true;
+      break;
+    case RID_IS_CONSTRUCTIBLE:
+      kind = CPTK_IS_CONSTRUCTIBLE;
+      variadic = true;
+      break;
     default:
       gcc_unreachable ();
     }
index d3249fedd8d89131329a2f69ff020cc59c4b102b..fa02b27145ac14b2d6c17c807d42e972a7621f32 100644 (file)
@@ -9211,6 +9211,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
       return type_code1 == UNION_TYPE;
 
+    case CPTK_IS_ASSIGNABLE:
+      return is_xible (MODIFY_EXPR, type1, type2);
+
+    case CPTK_IS_CONSTRUCTIBLE:
+      return is_xible (INIT_EXPR, type1, type2);
+
     default:
       gcc_unreachable ();
       return false;
@@ -9284,6 +9290,10 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
        return error_mark_node;
       break;
 
+    case CPTK_IS_ASSIGNABLE:
+    case CPTK_IS_CONSTRUCTIBLE:
+      break;
+
     case CPTK_IS_TRIVIALLY_ASSIGNABLE:
     case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
       if (!check_trait_type (type1)
diff --git a/gcc/testsuite/g++.dg/ext/80654.C b/gcc/testsuite/g++.dg/ext/80654.C
new file mode 100644 (file)
index 0000000..8679613
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++11 } }
+
+template <class T> struct wrap 
+{
+  T t;
+  wrap(const wrap& other) : t(other.t) {}
+};
+
+struct nocopy {
+  nocopy (const nocopy&) = delete;
+};
+
+int main ()
+{
+  static_assert(!__is_trivially_constructible(wrap<nocopy>,
+                                             const wrap<nocopy>&), "");
+  return 0;
+}
index c32dc62abca8c3ec1e29b73b44534f33d9e662c7..98d363acc2e1202fe6d9fa8eb871ac72573c5d5c 100644 (file)
@@ -1,3 +1,40 @@
+2017-05-17  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Implement new C++ intrinsics __is_assignable and __is_constructible.
+       * include/std/type_traits (__do_is_static_castable_impl): Remove.
+       (__is_static_castable_impl, __is_static_castable_safe): Likewise.
+       (__is_static_castable, __do_is_direct_constructible_impl): Likewise.
+       (__is_direct_constructible_impl): Likewise.
+       (__is_direct_constructible_new_safe): Likewise.
+       (__is_base_to_derived_ref, __is_lvalue_to_rvalue_ref): Likewise.
+       (__is_direct_constructible_ref_cast): Likewise.
+       (__is_direct_constructible_new, __is_direct_constructible): Likewise.
+       (__do_is_nary_constructible_impl): Likewise.
+       (__is_nary_constructible_impl, __is_nary_constructible): Likewise.
+       (__is_constructible_impl): Likewise.
+       (is_constructible): Call the intrinsic.
+       (__is_assignable_helper): Remove.
+       (is_assignable): Call the intrinsic.
+       (is_trivially_constructible): Likewise.
+       (__is_trivially_copy_constructible_impl): New.
+       (is_trivially_copy_constructible): Use it.
+       (__is_trivially_move_constructible_impl): New.
+       (is_trivially_move_constructible): Use it.
+       (is_trivially_assignable): Call the intrinsic.
+       (__is_trivially_copy_assignable_impl): New.
+       (is_trivially_copy_assignable): Use it.
+       (__is_trivially_move_assignable_impl): New.
+       (is_trivially_move_assignable): Use it.
+       (testsuite/20_util/declval/requirements/1_neg.cc): Adjust.
+       (testsuite/20_util/is_trivially_copy_assignable/value.cc):
+       Add test for void.
+       (testsuite/20_util/is_trivially_copy_constructible/value.cc): Likewise.
+       (testsuite/20_util/is_trivially_move_assignable/value.cc): Likewise.
+       (testsuite/20_util/is_trivially_move_constructible/value.cc): Likewise.
+       (testsuite/20_util/make_signed/requirements/typedefs_neg.cc): Adjust.
+       (testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc):
+       Likewise.
+
 2017-05-16  Jonathan Wakely  <jwakely@redhat.com>
 
        * testsuite/experimental/source_location/1.cc: Change expected result
index aac7cff6cf617df9d4f836584a249725c3f738cd..390b6f40af501add678168b64804806c97b28b39 100644 (file)
@@ -924,213 +924,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public __is_default_constructible_safe<_Tp>::type
     { };
 
-
-  // Implementation of is_constructible.
-
-  // The hardest part of this trait is the binary direct-initialization
-  // case, because we hit into a functional cast of the form T(arg).
-  // This implementation uses different strategies depending on the
-  // target type to reduce the test overhead as much as possible:
-  //
-  // a) For a reference target type, we use a static_cast expression
-  //    modulo its extra cases.
-  //
-  // b) For a non-reference target type we use a ::new expression.
-  struct __do_is_static_castable_impl
-  {
-    template<typename _From, typename _To, typename
-             = decltype(static_cast<_To>(declval<_From>()))>
-      static true_type __test(int);
-
-    template<typename, typename>
-      static false_type __test(...);
-  };
-
-  template<typename _From, typename _To>
-    struct __is_static_castable_impl
-    : public __do_is_static_castable_impl
-    {
-      typedef decltype(__test<_From, _To>(0)) type;
-    };
-
-  template<typename _From, typename _To>
-    struct __is_static_castable_safe
-    : public __is_static_castable_impl<_From, _To>::type
-    { };
-
-  // __is_static_castable
-  template<typename _From, typename _To>
-    struct __is_static_castable
-    : public integral_constant<bool, (__is_static_castable_safe<
-                                     _From, _To>::value)>
-    { };
-
-  // Implementation for non-reference types. To meet the proper
-  // variable definition semantics, we also need to test for
-  // is_destructible in this case.
-  // This form should be simplified by a single expression:
-  // ::delete ::new _Tp(declval<_Arg>()), see c++/51222.
-  struct __do_is_direct_constructible_impl
-  {
-    template<typename _Tp, typename _Arg, typename
-            = decltype(::new _Tp(declval<_Arg>()))>
-      static true_type __test(int);
-
-    template<typename, typename>
-      static false_type __test(...);
-  };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_direct_constructible_impl
-    : public __do_is_direct_constructible_impl
-    {
-      typedef decltype(__test<_Tp, _Arg>(0)) type;
-    };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_direct_constructible_new_safe
-    : public __and_<is_destructible<_Tp>,
-                    __is_direct_constructible_impl<_Tp, _Arg>>
-    { };
-
-  template<typename, typename>
-    struct is_same;
-
-  template<typename, typename>
-    struct is_base_of;
-
-  template<typename>
-    struct remove_reference;
-
-  template<typename _From, typename _To, bool
-           = __not_<__or_<is_void<_From>,
-                          is_function<_From>>>::value>
-    struct __is_base_to_derived_ref;
-
-  template<typename _Tp, typename... _Args>
-    struct is_constructible;
-
-  // Detect whether we have a downcast situation during
-  // reference binding.
-  template<typename _From, typename _To>
-    struct __is_base_to_derived_ref<_From, _To, true>
-    {
-      typedef typename remove_cv<typename remove_reference<_From
-        >::type>::type __src_t;
-      typedef typename remove_cv<typename remove_reference<_To
-        >::type>::type __dst_t;
-      typedef __and_<__not_<is_same<__src_t, __dst_t>>,
-                    is_base_of<__src_t, __dst_t>,
-                    __not_<is_constructible<__dst_t, _From>>> type;
-      static constexpr bool value = type::value;
-    };
-
-  template<typename _From, typename _To>
-    struct __is_base_to_derived_ref<_From, _To, false>
-    : public false_type
-    { };
-
-  template<typename _From, typename _To, bool
-           = __and_<is_lvalue_reference<_From>,
-                    is_rvalue_reference<_To>>::value>
-    struct __is_lvalue_to_rvalue_ref;
-
-  // Detect whether we have an lvalue of non-function type
-  // bound to a reference-compatible rvalue-reference.
-  template<typename _From, typename _To>
-    struct __is_lvalue_to_rvalue_ref<_From, _To, true>
-    {
-      typedef typename remove_cv<typename remove_reference<
-        _From>::type>::type __src_t;
-      typedef typename remove_cv<typename remove_reference<
-        _To>::type>::type __dst_t;
-      typedef __and_<__not_<is_function<__src_t>>,
-        __or_<is_same<__src_t, __dst_t>,
-                   is_base_of<__dst_t, __src_t>>> type;
-      static constexpr bool value = type::value;
-    };
-
-  template<typename _From, typename _To>
-    struct __is_lvalue_to_rvalue_ref<_From, _To, false>
-    : public false_type
-    { };
-
-  // Here we handle direct-initialization to a reference type as
-  // equivalent to a static_cast modulo overshooting conversions.
-  // These are restricted to the following conversions:
-  //    a) A base class value to a derived class reference
-  //    b) An lvalue to an rvalue-reference of reference-compatible
-  //       types that are not functions
-  template<typename _Tp, typename _Arg>
-    struct __is_direct_constructible_ref_cast
-    : public __and_<__is_static_castable<_Arg, _Tp>,
-                    __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
-                                 __is_lvalue_to_rvalue_ref<_Arg, _Tp>
-                   >>>
-    { };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_direct_constructible_new
-    : public conditional<is_reference<_Tp>::value,
-                        __is_direct_constructible_ref_cast<_Tp, _Arg>,
-                        __is_direct_constructible_new_safe<_Tp, _Arg>
-                        >::type
-    { };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_direct_constructible
-    : public __is_direct_constructible_new<_Tp, _Arg>::type
-    { };
-
-  // Since default-construction and binary direct-initialization have
-  // been handled separately, the implementation of the remaining
-  // n-ary construction cases is rather straightforward. We can use
-  // here a functional cast, because array types are excluded anyway
-  // and this form is never interpreted as a C cast.
-  struct __do_is_nary_constructible_impl
-  {
-    template<typename _Tp, typename... _Args, typename
-             = decltype(_Tp(declval<_Args>()...))>
-      static true_type __test(int);
-
-    template<typename, typename...>
-      static false_type __test(...);
-  };
-
-  template<typename _Tp, typename... _Args>
-    struct __is_nary_constructible_impl
-    : public __do_is_nary_constructible_impl
-    {
-      typedef decltype(__test<_Tp, _Args...>(0)) type;
-    };
-
-  template<typename _Tp, typename... _Args>
-    struct __is_nary_constructible
-    : public __is_nary_constructible_impl<_Tp, _Args...>::type
-    {
-      static_assert(sizeof...(_Args) > 1,
-                    "Only useful for > 1 arguments");
-    };
-
-  template<typename _Tp, typename... _Args>
-    struct __is_constructible_impl
-    : public __is_nary_constructible<_Tp, _Args...>
-    { };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_constructible_impl<_Tp, _Arg>
-    : public __is_direct_constructible<_Tp, _Arg>
-    { };
-
-  template<typename _Tp>
-    struct __is_constructible_impl<_Tp>
-    : public is_default_constructible<_Tp>
-    { };
-
   /// is_constructible
   template<typename _Tp, typename... _Args>
     struct is_constructible
-    : public __is_constructible_impl<_Tp, _Args...>::type
+      : public __bool_constant<__is_constructible(_Tp, _Args...)>
     { };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
@@ -1255,26 +1052,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public __is_nothrow_move_constructible_impl<_Tp>
     { };
 
-  template<typename _Tp, typename _Up>
-    class __is_assignable_helper
-    {
-      template<typename _Tp1, typename _Up1,
-              typename = decltype(declval<_Tp1>() = declval<_Up1>())>
-       static true_type
-       __test(int);
-
-      template<typename, typename>
-       static false_type
-       __test(...);
-
-    public:
-      typedef decltype(__test<_Tp, _Up>(0)) type;
-    };
-
   /// is_assignable
   template<typename _Tp, typename _Up>
     struct is_assignable
-      : public __is_assignable_helper<_Tp, _Up>::type
+      : public __bool_constant<__is_assignable(_Tp, _Up)>
     { };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
@@ -1364,8 +1145,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// is_trivially_constructible
   template<typename _Tp, typename... _Args>
     struct is_trivially_constructible
-    : public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool,
-                       __is_trivially_constructible(_Tp, _Args...)>>
+    : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)>
     { };
 
   /// is_trivially_default_constructible
@@ -1405,45 +1185,95 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   { };
 
   /// is_trivially_copy_constructible
+
+  template<typename _Tp, bool = __is_referenceable<_Tp>::value>
+    struct __is_trivially_copy_constructible_impl;
+
   template<typename _Tp>
-    struct is_trivially_copy_constructible
+    struct __is_trivially_copy_constructible_impl<_Tp, false>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_trivially_copy_constructible_impl<_Tp, true>
     : public __and_<is_copy_constructible<_Tp>,
                    integral_constant<bool,
                        __is_trivially_constructible(_Tp, const _Tp&)>>
     { };
 
+  template<typename _Tp>
+    struct is_trivially_copy_constructible
+    : public __is_trivially_copy_constructible_impl<_Tp>
+    { };
+
   /// is_trivially_move_constructible
+
+  template<typename _Tp, bool = __is_referenceable<_Tp>::value>
+    struct __is_trivially_move_constructible_impl;
+
   template<typename _Tp>
-    struct is_trivially_move_constructible
+    struct __is_trivially_move_constructible_impl<_Tp, false>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_trivially_move_constructible_impl<_Tp, true>
     : public __and_<is_move_constructible<_Tp>,
                    integral_constant<bool,
                        __is_trivially_constructible(_Tp, _Tp&&)>>
     { };
 
+  template<typename _Tp>
+    struct is_trivially_move_constructible
+    : public __is_trivially_move_constructible_impl<_Tp>
+    { };
+
   /// is_trivially_assignable
   template<typename _Tp, typename _Up>
     struct is_trivially_assignable
-    : public __and_<is_assignable<_Tp, _Up>,
-                   integral_constant<bool,
-                       __is_trivially_assignable(_Tp, _Up)>>
+    : public __bool_constant<__is_trivially_assignable(_Tp, _Up)>
     { };
 
   /// is_trivially_copy_assignable
+
+  template<typename _Tp, bool = __is_referenceable<_Tp>::value>
+    struct __is_trivially_copy_assignable_impl;
+
   template<typename _Tp>
-    struct is_trivially_copy_assignable
+    struct __is_trivially_copy_assignable_impl<_Tp, false>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_trivially_copy_assignable_impl<_Tp, true>
     : public __and_<is_copy_assignable<_Tp>,
                    integral_constant<bool,
                        __is_trivially_assignable(_Tp&, const _Tp&)>>
     { };
 
+  template<typename _Tp>
+    struct is_trivially_copy_assignable
+    : public __is_trivially_copy_assignable_impl<_Tp>
+    { };
+
   /// is_trivially_move_assignable
+
+  template<typename _Tp, bool = __is_referenceable<_Tp>::value>
+    struct __is_trivially_move_assignable_impl;
+
   template<typename _Tp>
-    struct is_trivially_move_assignable
+    struct __is_trivially_move_assignable_impl<_Tp, false>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_trivially_move_assignable_impl<_Tp, true>
     : public __and_<is_move_assignable<_Tp>,
                    integral_constant<bool,
                        __is_trivially_assignable(_Tp&, _Tp&&)>>
     { };
 
+  template<typename _Tp>
+    struct is_trivially_move_assignable
+    : public __is_trivially_move_assignable_impl<_Tp>
+    { };
+
   /// is_trivially_destructible
   template<typename _Tp>
     struct is_trivially_destructible
index dc9daeb42ce5254ec274babb84f4ad48d81bb29d..4e254e8919158b84d41d1ef7fbfb42c82cafebf0 100644 (file)
@@ -18,7 +18,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-error "static assertion failed" "" { target *-*-* } 2259 }
+// { dg-error "static assertion failed" "" { target *-*-* } 2089 }
 
 #include <utility>
 
index b002246dfd51d314c4ce9c7dc462863e74721cdc..902aa5e59322605b4e977e4d7cf13ee19928c73f 100644 (file)
@@ -88,4 +88,6 @@ void test01()
                MoveOnly>(false), "");
   static_assert(test_property<is_trivially_copy_assignable, 
                MoveOnly2>(false), "");
+  static_assert(test_property<is_trivially_copy_assignable,
+               void>(false), "");
 }
index 845e058615126eada7e5b1b5e866c240798c5687..627410bdc3093f3e8c973f48c7ed00ffcf33ee52 100644 (file)
@@ -82,4 +82,6 @@ void test01()
                MoveOnly>(false), "");
   static_assert(test_property<is_trivially_copy_constructible, 
                MoveOnly2>(false), "");
+  static_assert(test_property<is_trivially_copy_constructible,
+               void>(false), "");
 }
index 68833b67f12ed26cc3d760c02b4d1e5a8668f448..221048347a2218efb0708a7be8379f85a068c9f8 100644 (file)
@@ -88,4 +88,6 @@ void test01()
                MoveOnly>(true), "");
   static_assert(test_property<is_trivially_move_assignable, 
                MoveOnly2>(false), "");
+  static_assert(test_property<is_trivially_move_assignable, 
+               void>(false), "");
 }
index ad6045bda813c425bf56bb55502479a71bb0983b..9a21b6e2133d7ac18b0e83390798a5d02d65e0e2 100644 (file)
@@ -82,4 +82,6 @@ void test01()
                MoveOnly>(true), "");
   static_assert(test_property<is_trivially_move_constructible, 
                MoveOnly2>(false), "");
+  static_assert(test_property<is_trivially_move_constructible,
+               void>(false), "");
 }
index 664fb70fb4b436d5f086c68948c93f07e7df3e4e..e3e80f919799e8ff106a8bb92561744b74f5b2d5 100644 (file)
@@ -47,4 +47,4 @@ void test01()
 // { dg-error "required from here" "" { target *-*-* } 39 }
 // { dg-error "required from here" "" { target *-*-* } 41 }
 
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1924 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1754 }
index 6d6471755f744ac485e03d92d437eef8806d9e74..86b0c2d6da717998c65516d6e39d906b6c05d581 100644 (file)
@@ -47,5 +47,5 @@ void test01()
 // { dg-error "required from here" "" { target *-*-* } 39 }
 // { dg-error "required from here" "" { target *-*-* } 41 }
 
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1820 }
-// { dg-error "declaration of" "" { target *-*-* } 1777 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1650 }
+