Commit b42cc3ca by Ville Voutilainen Committed by Ville Voutilainen

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
parent 36f4bc9c
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[] = ...@@ -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 ...@@ -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,
......
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 ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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,22 +1199,36 @@ constructible_expr (tree to, tree from) ...@@ -1198,22 +1199,36 @@ constructible_expr (tree to, tree from)
return expr; 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 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. */
bool static tree
is_trivially_xible (enum tree_code code, tree to, tree from) is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
{ {
if (VOID_TYPE_P (to)) if (VOID_TYPE_P (to) || ABSTRACT_CLASS_TYPE_P (to)
return false; || (from && FUNC_OR_METHOD_TYPE_P (from)
&& (TYPE_READONLY (from) || FUNCTION_REF_QUALIFIED (from))))
return error_mark_node;
tree expr; tree expr;
if (code == MODIFY_EXPR) if (code == MODIFY_EXPR)
expr = assignable_expr (to, from); expr = assignable_expr (to, from);
else if (from && TREE_CHAIN (from)) else if (trivial && from && TREE_CHAIN (from))
return false; // only 0- and 1-argument ctors can be trivial return error_mark_node; // only 0- and 1-argument ctors can be trivial
else else
expr = constructible_expr (to, from); 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) if (expr == error_mark_node)
return false; return false;
...@@ -1221,6 +1236,19 @@ is_trivially_xible (enum tree_code code, tree to, tree from) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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)
......
// { 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;
}
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
......
...@@ -18,7 +18,7 @@ ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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 }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment