Implement new C++ intrinsics __is_assignable and __is_constructible.
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
This commit is contained in:
parent
36f4bc9ce8
commit
b42cc3ca24
@ -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>
|
2017-05-17 Martin Liska <mliska@suse.cz>
|
||||||
|
|
||||||
* c-common.h: Introduce dump_flags_t type and
|
* c-common.h: Introduce dump_flags_t type and
|
||||||
|
@ -514,6 +514,8 @@ const struct c_common_resword c_common_reswords[] =
|
|||||||
{ "volatile", RID_VOLATILE, 0 },
|
{ "volatile", RID_VOLATILE, 0 },
|
||||||
{ "wchar_t", RID_WCHAR, D_CXXONLY },
|
{ "wchar_t", RID_WCHAR, D_CXXONLY },
|
||||||
{ "while", RID_WHILE, 0 },
|
{ "while", RID_WHILE, 0 },
|
||||||
|
{ "__is_assignable", RID_IS_ASSIGNABLE, D_CXXONLY },
|
||||||
|
{ "__is_constructible", RID_IS_CONSTRUCTIBLE, D_CXXONLY },
|
||||||
|
|
||||||
/* C++ transactional memory. */
|
/* C++ transactional memory. */
|
||||||
{ "synchronized", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM },
|
{ "synchronized", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM },
|
||||||
|
@ -172,6 +172,7 @@ enum rid
|
|||||||
RID_IS_TRIVIALLY_ASSIGNABLE, RID_IS_TRIVIALLY_CONSTRUCTIBLE,
|
RID_IS_TRIVIALLY_ASSIGNABLE, RID_IS_TRIVIALLY_CONSTRUCTIBLE,
|
||||||
RID_IS_TRIVIALLY_COPYABLE,
|
RID_IS_TRIVIALLY_COPYABLE,
|
||||||
RID_IS_UNION, RID_UNDERLYING_TYPE,
|
RID_IS_UNION, RID_UNDERLYING_TYPE,
|
||||||
|
RID_IS_ASSIGNABLE, RID_IS_CONSTRUCTIBLE,
|
||||||
|
|
||||||
/* C++11 */
|
/* C++11 */
|
||||||
RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
|
RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
|
||||||
|
@ -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>
|
2017-05-17 Nathan Sidwell <nathan@acm.org>
|
||||||
|
|
||||||
* cp-tree.h (ovl_iterator::using_p): New predicate.
|
* cp-tree.h (ovl_iterator::using_p): New predicate.
|
||||||
|
@ -1016,7 +1016,9 @@ enum cp_trait_kind
|
|||||||
CPTK_IS_TRIVIALLY_CONSTRUCTIBLE,
|
CPTK_IS_TRIVIALLY_CONSTRUCTIBLE,
|
||||||
CPTK_IS_TRIVIALLY_COPYABLE,
|
CPTK_IS_TRIVIALLY_COPYABLE,
|
||||||
CPTK_IS_UNION,
|
CPTK_IS_UNION,
|
||||||
CPTK_UNDERLYING_TYPE
|
CPTK_UNDERLYING_TYPE,
|
||||||
|
CPTK_IS_ASSIGNABLE,
|
||||||
|
CPTK_IS_CONSTRUCTIBLE
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The types that we are processing. */
|
/* The types that we are processing. */
|
||||||
@ -6227,6 +6229,7 @@ extern void use_thunk (tree, bool);
|
|||||||
extern bool trivial_fn_p (tree);
|
extern bool trivial_fn_p (tree);
|
||||||
extern tree forward_parm (tree);
|
extern tree forward_parm (tree);
|
||||||
extern bool is_trivially_xible (enum tree_code, tree, 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 get_defaulted_eh_spec (tree);
|
||||||
extern tree unevaluated_noexcept_spec (void);
|
extern tree unevaluated_noexcept_spec (void);
|
||||||
extern void after_nsdmi_defaulted_late_checks (tree);
|
extern void after_nsdmi_defaulted_late_checks (tree);
|
||||||
|
@ -2634,6 +2634,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
|
|||||||
case CPTK_IS_LITERAL_TYPE:
|
case CPTK_IS_LITERAL_TYPE:
|
||||||
pp_cxx_ws_string (pp, "__is_literal_type");
|
pp_cxx_ws_string (pp, "__is_literal_type");
|
||||||
break;
|
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:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
|
@ -1162,6 +1162,7 @@ constructible_expr (tree to, tree from)
|
|||||||
{
|
{
|
||||||
tree ctype = to;
|
tree ctype = to;
|
||||||
vec<tree, va_gc> *args = NULL;
|
vec<tree, va_gc> *args = NULL;
|
||||||
|
cp_unevaluated cp_uneval_guard;
|
||||||
if (TREE_CODE (to) != REFERENCE_TYPE)
|
if (TREE_CODE (to) != REFERENCE_TYPE)
|
||||||
to = cp_build_reference_type (to, /*rval*/false);
|
to = cp_build_reference_type (to, /*rval*/false);
|
||||||
tree ob = build_stub_object (to);
|
tree ob = build_stub_object (to);
|
||||||
@ -1198,6 +1199,27 @@ constructible_expr (tree to, tree from)
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
|
||||||
|
{
|
||||||
|
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 (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
|
/* Returns true iff TO is trivially assignable (if CODE is MODIFY_EXPR) or
|
||||||
constructible (otherwise) from FROM, which is a single type for
|
constructible (otherwise) from FROM, which is a single type for
|
||||||
assignment or a list of types for construction. */
|
assignment or a list of types for construction. */
|
||||||
@ -1205,15 +1227,8 @@ constructible_expr (tree to, tree from)
|
|||||||
bool
|
bool
|
||||||
is_trivially_xible (enum tree_code code, tree to, tree from)
|
is_trivially_xible (enum tree_code code, tree to, tree from)
|
||||||
{
|
{
|
||||||
if (VOID_TYPE_P (to))
|
|
||||||
return false;
|
|
||||||
tree expr;
|
tree expr;
|
||||||
if (code == MODIFY_EXPR)
|
expr = is_xible_helper (code, to, from, /*trivial*/true);
|
||||||
expr = assignable_expr (to, from);
|
|
||||||
else if (from && TREE_CHAIN (from))
|
|
||||||
return false; // only 0- and 1-argument ctors can be trivial
|
|
||||||
else
|
|
||||||
expr = constructible_expr (to, from);
|
|
||||||
|
|
||||||
if (expr == error_mark_node)
|
if (expr == error_mark_node)
|
||||||
return false;
|
return false;
|
||||||
@ -1221,6 +1236,19 @@ is_trivially_xible (enum tree_code code, tree to, tree from)
|
|||||||
return !nt;
|
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
|
/* Subroutine of synthesized_method_walk. Update SPEC_P, TRIVIAL_P and
|
||||||
DELETED_P or give an error message MSG with argument ARG. */
|
DELETED_P or give an error message MSG with argument ARG. */
|
||||||
|
|
||||||
|
@ -5135,6 +5135,8 @@ cp_parser_primary_expression (cp_parser *parser,
|
|||||||
case RID_IS_TRIVIALLY_CONSTRUCTIBLE:
|
case RID_IS_TRIVIALLY_CONSTRUCTIBLE:
|
||||||
case RID_IS_TRIVIALLY_COPYABLE:
|
case RID_IS_TRIVIALLY_COPYABLE:
|
||||||
case RID_IS_UNION:
|
case RID_IS_UNION:
|
||||||
|
case RID_IS_ASSIGNABLE:
|
||||||
|
case RID_IS_CONSTRUCTIBLE:
|
||||||
return cp_parser_trait_expr (parser, token->keyword);
|
return cp_parser_trait_expr (parser, token->keyword);
|
||||||
|
|
||||||
// C++ concepts
|
// C++ concepts
|
||||||
@ -9686,6 +9688,14 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
|
|||||||
case RID_DIRECT_BASES:
|
case RID_DIRECT_BASES:
|
||||||
kind = CPTK_DIRECT_BASES;
|
kind = CPTK_DIRECT_BASES;
|
||||||
break;
|
break;
|
||||||
|
case RID_IS_ASSIGNABLE:
|
||||||
|
kind = CPTK_IS_ASSIGNABLE;
|
||||||
|
binary = true;
|
||||||
|
break;
|
||||||
|
case RID_IS_CONSTRUCTIBLE:
|
||||||
|
kind = CPTK_IS_CONSTRUCTIBLE;
|
||||||
|
variadic = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
}
|
}
|
||||||
|
@ -9211,6 +9211,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
|
|||||||
case CPTK_IS_UNION:
|
case CPTK_IS_UNION:
|
||||||
return type_code1 == UNION_TYPE;
|
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:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
return false;
|
return false;
|
||||||
@ -9284,6 +9290,10 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
|
|||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CPTK_IS_ASSIGNABLE:
|
||||||
|
case CPTK_IS_CONSTRUCTIBLE:
|
||||||
|
break;
|
||||||
|
|
||||||
case CPTK_IS_TRIVIALLY_ASSIGNABLE:
|
case CPTK_IS_TRIVIALLY_ASSIGNABLE:
|
||||||
case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
|
case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
|
||||||
if (!check_trait_type (type1)
|
if (!check_trait_type (type1)
|
||||||
|
18
gcc/testsuite/g++.dg/ext/80654.C
Normal file
18
gcc/testsuite/g++.dg/ext/80654.C
Normal file
@ -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;
|
||||||
|
}
|
@ -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>
|
2017-05-16 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
* testsuite/experimental/source_location/1.cc: Change expected result
|
* testsuite/experimental/source_location/1.cc: Change expected result
|
||||||
|
@ -924,213 +924,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
: public __is_default_constructible_safe<_Tp>::type
|
: 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
|
/// is_constructible
|
||||||
template<typename _Tp, typename... _Args>
|
template<typename _Tp, typename... _Args>
|
||||||
struct is_constructible
|
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>
|
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||||
@ -1255,26 +1052,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
: public __is_nothrow_move_constructible_impl<_Tp>
|
: 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
|
/// is_assignable
|
||||||
template<typename _Tp, typename _Up>
|
template<typename _Tp, typename _Up>
|
||||||
struct is_assignable
|
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>
|
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||||
@ -1364,8 +1145,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
/// is_trivially_constructible
|
/// is_trivially_constructible
|
||||||
template<typename _Tp, typename... _Args>
|
template<typename _Tp, typename... _Args>
|
||||||
struct is_trivially_constructible
|
struct is_trivially_constructible
|
||||||
: public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool,
|
: public __bool_constant<__is_trivially_constructible(_Tp, _Args...)>
|
||||||
__is_trivially_constructible(_Tp, _Args...)>>
|
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
/// is_trivially_default_constructible
|
/// is_trivially_default_constructible
|
||||||
@ -1405,45 +1185,95 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
{ };
|
{ };
|
||||||
|
|
||||||
/// is_trivially_copy_constructible
|
/// is_trivially_copy_constructible
|
||||||
|
|
||||||
|
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||||
|
struct __is_trivially_copy_constructible_impl;
|
||||||
|
|
||||||
template<typename _Tp>
|
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>,
|
: public __and_<is_copy_constructible<_Tp>,
|
||||||
integral_constant<bool,
|
integral_constant<bool,
|
||||||
__is_trivially_constructible(_Tp, const _Tp&)>>
|
__is_trivially_constructible(_Tp, const _Tp&)>>
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
/// is_trivially_move_constructible
|
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
struct is_trivially_move_constructible
|
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_impl<_Tp, false>
|
||||||
|
: public false_type { };
|
||||||
|
|
||||||
|
template<typename _Tp>
|
||||||
|
struct __is_trivially_move_constructible_impl<_Tp, true>
|
||||||
: public __and_<is_move_constructible<_Tp>,
|
: public __and_<is_move_constructible<_Tp>,
|
||||||
integral_constant<bool,
|
integral_constant<bool,
|
||||||
__is_trivially_constructible(_Tp, _Tp&&)>>
|
__is_trivially_constructible(_Tp, _Tp&&)>>
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
|
template<typename _Tp>
|
||||||
|
struct is_trivially_move_constructible
|
||||||
|
: public __is_trivially_move_constructible_impl<_Tp>
|
||||||
|
{ };
|
||||||
|
|
||||||
/// is_trivially_assignable
|
/// is_trivially_assignable
|
||||||
template<typename _Tp, typename _Up>
|
template<typename _Tp, typename _Up>
|
||||||
struct is_trivially_assignable
|
struct is_trivially_assignable
|
||||||
: public __and_<is_assignable<_Tp, _Up>,
|
: public __bool_constant<__is_trivially_assignable(_Tp, _Up)>
|
||||||
integral_constant<bool,
|
|
||||||
__is_trivially_assignable(_Tp, _Up)>>
|
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
/// is_trivially_copy_assignable
|
/// is_trivially_copy_assignable
|
||||||
|
|
||||||
|
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||||
|
struct __is_trivially_copy_assignable_impl;
|
||||||
|
|
||||||
template<typename _Tp>
|
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>,
|
: public __and_<is_copy_assignable<_Tp>,
|
||||||
integral_constant<bool,
|
integral_constant<bool,
|
||||||
__is_trivially_assignable(_Tp&, const _Tp&)>>
|
__is_trivially_assignable(_Tp&, const _Tp&)>>
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
/// is_trivially_move_assignable
|
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
struct is_trivially_move_assignable
|
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_impl<_Tp, false>
|
||||||
|
: public false_type { };
|
||||||
|
|
||||||
|
template<typename _Tp>
|
||||||
|
struct __is_trivially_move_assignable_impl<_Tp, true>
|
||||||
: public __and_<is_move_assignable<_Tp>,
|
: public __and_<is_move_assignable<_Tp>,
|
||||||
integral_constant<bool,
|
integral_constant<bool,
|
||||||
__is_trivially_assignable(_Tp&, _Tp&&)>>
|
__is_trivially_assignable(_Tp&, _Tp&&)>>
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
|
template<typename _Tp>
|
||||||
|
struct is_trivially_move_assignable
|
||||||
|
: public __is_trivially_move_assignable_impl<_Tp>
|
||||||
|
{ };
|
||||||
|
|
||||||
/// is_trivially_destructible
|
/// is_trivially_destructible
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
struct is_trivially_destructible
|
struct is_trivially_destructible
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// with this library; see the file COPYING3. If not see
|
// with this library; see the file COPYING3. If not see
|
||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// { dg-error "static assertion failed" "" { target *-*-* } 2259 }
|
// { dg-error "static assertion failed" "" { target *-*-* } 2089 }
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -88,4 +88,6 @@ void test01()
|
|||||||
MoveOnly>(false), "");
|
MoveOnly>(false), "");
|
||||||
static_assert(test_property<is_trivially_copy_assignable,
|
static_assert(test_property<is_trivially_copy_assignable,
|
||||||
MoveOnly2>(false), "");
|
MoveOnly2>(false), "");
|
||||||
|
static_assert(test_property<is_trivially_copy_assignable,
|
||||||
|
void>(false), "");
|
||||||
}
|
}
|
||||||
|
@ -82,4 +82,6 @@ void test01()
|
|||||||
MoveOnly>(false), "");
|
MoveOnly>(false), "");
|
||||||
static_assert(test_property<is_trivially_copy_constructible,
|
static_assert(test_property<is_trivially_copy_constructible,
|
||||||
MoveOnly2>(false), "");
|
MoveOnly2>(false), "");
|
||||||
|
static_assert(test_property<is_trivially_copy_constructible,
|
||||||
|
void>(false), "");
|
||||||
}
|
}
|
||||||
|
@ -88,4 +88,6 @@ void test01()
|
|||||||
MoveOnly>(true), "");
|
MoveOnly>(true), "");
|
||||||
static_assert(test_property<is_trivially_move_assignable,
|
static_assert(test_property<is_trivially_move_assignable,
|
||||||
MoveOnly2>(false), "");
|
MoveOnly2>(false), "");
|
||||||
|
static_assert(test_property<is_trivially_move_assignable,
|
||||||
|
void>(false), "");
|
||||||
}
|
}
|
||||||
|
@ -82,4 +82,6 @@ void test01()
|
|||||||
MoveOnly>(true), "");
|
MoveOnly>(true), "");
|
||||||
static_assert(test_property<is_trivially_move_constructible,
|
static_assert(test_property<is_trivially_move_constructible,
|
||||||
MoveOnly2>(false), "");
|
MoveOnly2>(false), "");
|
||||||
|
static_assert(test_property<is_trivially_move_constructible,
|
||||||
|
void>(false), "");
|
||||||
}
|
}
|
||||||
|
@ -47,4 +47,4 @@ void test01()
|
|||||||
// { dg-error "required from here" "" { target *-*-* } 39 }
|
// { dg-error "required from here" "" { target *-*-* } 39 }
|
||||||
// { dg-error "required from here" "" { target *-*-* } 41 }
|
// { 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 }
|
||||||
|
@ -47,5 +47,5 @@ void test01()
|
|||||||
// { dg-error "required from here" "" { target *-*-* } 39 }
|
// { dg-error "required from here" "" { target *-*-* } 39 }
|
||||||
// { dg-error "required from here" "" { target *-*-* } 41 }
|
// { dg-error "required from here" "" { target *-*-* } 41 }
|
||||||
|
|
||||||
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1820 }
|
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1650 }
|
||||||
// { dg-error "declaration of" "" { target *-*-* } 1777 }
|
|
||||||
|
Loading…
Reference in New Issue
Block a user