c-common.h (enum rid): Add RID_IS_TRIVIALLY_ASSIGNABLE and RID_IS_TRIVIALLY_CONSTRUCTIBLE.
c-family/ * c-common.h (enum rid): Add RID_IS_TRIVIALLY_ASSIGNABLE and RID_IS_TRIVIALLY_CONSTRUCTIBLE. * c-common.c (c_common_reswords): Add __is_trivially_copyable. cp/ * cp-tree.h (cp_trait_kind): Add CPTK_IS_TRIVIALLY_ASSIGNABLE and CPTK_IS_TRIVIALLY_CONSTRUCTIBLE. * cxx-pretty-print.c (pp_cxx_trait_expression): Likewise. * parser.c (cp_parser_primary_expression): Likewise. (cp_parser_trait_expr): Likewise. Handle variadic trait. * semantics.c (trait_expr_value): Likewise. (finish_trait_expr): Likewise. (check_trait_type): Handle variadic trait. Return bool. * method.c (build_stub_object): Add rvalue reference here. (locate_fn_flags): Not here. (check_nontriv, assignable_expr, constructible_expr): New. (is_trivially_xible): New. From-SVN: r215738
This commit is contained in:
parent
b752325e94
commit
dd5d5481be
@ -1,5 +1,9 @@
|
||||
2014-09-30 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* c-common.h (enum rid): Add RID_IS_TRIVIALLY_ASSIGNABLE and
|
||||
RID_IS_TRIVIALLY_CONSTRUCTIBLE.
|
||||
* c-common.c (c_common_reswords): Add __is_trivially_copyable.
|
||||
|
||||
* c-common.h (enum rid): Add RID_IS_TRIVIALLY_COPYABLE.
|
||||
* c-common.c (c_common_reswords): Add __is_trivially_copyable.
|
||||
|
||||
|
@ -480,6 +480,8 @@ const struct c_common_resword c_common_reswords[] =
|
||||
{ "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY },
|
||||
{ "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY },
|
||||
{ "__is_trivial", RID_IS_TRIVIAL, D_CXXONLY },
|
||||
{ "__is_trivially_assignable", RID_IS_TRIVIALLY_ASSIGNABLE, D_CXXONLY },
|
||||
{ "__is_trivially_constructible", RID_IS_TRIVIALLY_CONSTRUCTIBLE, D_CXXONLY },
|
||||
{ "__is_trivially_copyable", RID_IS_TRIVIALLY_COPYABLE, D_CXXONLY },
|
||||
{ "__is_union", RID_IS_UNION, D_CXXONLY },
|
||||
{ "__label__", RID_LABEL, 0 },
|
||||
|
@ -143,6 +143,7 @@ enum rid
|
||||
RID_IS_FINAL, RID_IS_LITERAL_TYPE,
|
||||
RID_IS_POD, RID_IS_POLYMORPHIC,
|
||||
RID_IS_STD_LAYOUT, RID_IS_TRIVIAL,
|
||||
RID_IS_TRIVIALLY_ASSIGNABLE, RID_IS_TRIVIALLY_CONSTRUCTIBLE,
|
||||
RID_IS_TRIVIALLY_COPYABLE,
|
||||
RID_IS_UNION, RID_UNDERLYING_TYPE,
|
||||
|
||||
|
@ -1,5 +1,18 @@
|
||||
2014-09-30 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* cp-tree.h (cp_trait_kind): Add CPTK_IS_TRIVIALLY_ASSIGNABLE and
|
||||
CPTK_IS_TRIVIALLY_CONSTRUCTIBLE.
|
||||
* cxx-pretty-print.c (pp_cxx_trait_expression): Likewise.
|
||||
* parser.c (cp_parser_primary_expression): Likewise.
|
||||
(cp_parser_trait_expr): Likewise. Handle variadic trait.
|
||||
* semantics.c (trait_expr_value): Likewise.
|
||||
(finish_trait_expr): Likewise.
|
||||
(check_trait_type): Handle variadic trait. Return bool.
|
||||
* method.c (build_stub_object): Add rvalue reference here.
|
||||
(locate_fn_flags): Not here.
|
||||
(check_nontriv, assignable_expr, constructible_expr): New.
|
||||
(is_trivially_xible): New.
|
||||
|
||||
* cp-tree.h (cp_trait_kind): Add CPTK_IS_TRIVIALLY_COPYABLE.
|
||||
* cxx-pretty-print.c (pp_cxx_trait_expression): Likewise.
|
||||
* parser.c (cp_parser_primary_expression): Likewise.
|
||||
|
@ -653,6 +653,8 @@ typedef enum cp_trait_kind
|
||||
CPTK_IS_POLYMORPHIC,
|
||||
CPTK_IS_STD_LAYOUT,
|
||||
CPTK_IS_TRIVIAL,
|
||||
CPTK_IS_TRIVIALLY_ASSIGNABLE,
|
||||
CPTK_IS_TRIVIALLY_CONSTRUCTIBLE,
|
||||
CPTK_IS_TRIVIALLY_COPYABLE,
|
||||
CPTK_IS_UNION,
|
||||
CPTK_UNDERLYING_TYPE
|
||||
@ -5521,6 +5523,7 @@ extern tree make_thunk (tree, bool, tree, tree);
|
||||
extern void finish_thunk (tree);
|
||||
extern void use_thunk (tree, bool);
|
||||
extern bool trivial_fn_p (tree);
|
||||
extern bool is_trivially_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);
|
||||
|
@ -2393,6 +2393,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
|
||||
case CPTK_IS_TRIVIAL:
|
||||
pp_cxx_ws_string (pp, "__is_trivial");
|
||||
break;
|
||||
case CPTK_IS_TRIVIALLY_ASSIGNABLE:
|
||||
pp_cxx_ws_string (pp, "__is_trivially_assignable");
|
||||
break;
|
||||
case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
|
||||
pp_cxx_ws_string (pp, "__is_trivially_constructible");
|
||||
break;
|
||||
case CPTK_IS_TRIVIALLY_COPYABLE:
|
||||
pp_cxx_ws_string (pp, "__is_trivially_copyable");
|
||||
break;
|
||||
|
111
gcc/cp/method.c
111
gcc/cp/method.c
@ -852,6 +852,8 @@ build_stub_type (tree type, int quals, bool rvalue)
|
||||
static tree
|
||||
build_stub_object (tree reftype)
|
||||
{
|
||||
if (TREE_CODE (reftype) != REFERENCE_TYPE)
|
||||
reftype = cp_build_reference_type (reftype, /*rval*/true);
|
||||
tree stub = build1 (CONVERT_EXPR, reftype, integer_one_node);
|
||||
return convert_from_reference (stub);
|
||||
}
|
||||
@ -889,8 +891,6 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags,
|
||||
elt = TREE_CHAIN (elt))
|
||||
{
|
||||
tree type = TREE_VALUE (elt);
|
||||
if (TREE_CODE (type) != REFERENCE_TYPE)
|
||||
type = cp_build_reference_type (type, /*rval*/true);
|
||||
tree arg = build_stub_object (type);
|
||||
vec_safe_push (args, arg);
|
||||
}
|
||||
@ -1001,6 +1001,113 @@ get_inherited_ctor (tree ctor)
|
||||
return fn;
|
||||
}
|
||||
|
||||
/* walk_tree helper function for is_trivially_xible. If *TP is a call,
|
||||
return it if it calls something other than a trivial special member
|
||||
function. */
|
||||
|
||||
static tree
|
||||
check_nontriv (tree *tp, int *, void *)
|
||||
{
|
||||
tree fn;
|
||||
if (TREE_CODE (*tp) == CALL_EXPR)
|
||||
fn = CALL_EXPR_FN (*tp);
|
||||
else if (TREE_CODE (*tp) == AGGR_INIT_EXPR)
|
||||
fn = AGGR_INIT_EXPR_FN (*tp);
|
||||
else
|
||||
return NULL_TREE;
|
||||
|
||||
if (TREE_CODE (fn) == ADDR_EXPR)
|
||||
fn = TREE_OPERAND (fn, 0);
|
||||
|
||||
if (TREE_CODE (fn) != FUNCTION_DECL
|
||||
|| !trivial_fn_p (fn))
|
||||
return fn;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Return declval<T>() = declval<U>() treated as an unevaluated operand. */
|
||||
|
||||
static tree
|
||||
assignable_expr (tree to, tree from)
|
||||
{
|
||||
++cp_unevaluated_operand;
|
||||
to = build_stub_object (to);
|
||||
from = build_stub_object (from);
|
||||
tree r = cp_build_modify_expr (to, NOP_EXPR, from, tf_none);
|
||||
--cp_unevaluated_operand;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* The predicate condition for a template specialization
|
||||
is_constructible<T, Args...> shall be satisfied if and only if the
|
||||
following variable definition would be well-formed for some invented
|
||||
variable t: T t(create<Args>()...);
|
||||
|
||||
Return something equivalent in well-formedness and triviality. */
|
||||
|
||||
static tree
|
||||
constructible_expr (tree to, tree from)
|
||||
{
|
||||
tree expr;
|
||||
if (CLASS_TYPE_P (to))
|
||||
{
|
||||
tree ctype = to;
|
||||
vec<tree, va_gc> *args = NULL;
|
||||
if (TREE_CODE (to) != REFERENCE_TYPE)
|
||||
to = cp_build_reference_type (to, /*rval*/false);
|
||||
tree ob = build_stub_object (to);
|
||||
for (; from; from = TREE_CHAIN (from))
|
||||
vec_safe_push (args, build_stub_object (TREE_VALUE (from)));
|
||||
expr = build_special_member_call (ob, complete_ctor_identifier, &args,
|
||||
ctype, LOOKUP_NORMAL, tf_none);
|
||||
if (expr == error_mark_node)
|
||||
return error_mark_node;
|
||||
/* The current state of the standard vis-a-vis LWG 2116 is that
|
||||
is_*constructible involves destruction as well. */
|
||||
if (type_build_dtor_call (ctype))
|
||||
{
|
||||
tree dtor = build_special_member_call (ob, complete_dtor_identifier,
|
||||
NULL, ctype, LOOKUP_NORMAL,
|
||||
tf_none);
|
||||
if (dtor == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (ctype))
|
||||
expr = build2 (COMPOUND_EXPR, void_type_node, expr, dtor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TREE_CHAIN (from))
|
||||
return error_mark_node; // too many initializers
|
||||
from = build_stub_object (TREE_VALUE (from));
|
||||
expr = perform_direct_initialization_if_possible (to, from,
|
||||
/*cast*/false,
|
||||
tf_none);
|
||||
}
|
||||
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;
|
||||
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
|
||||
expr = constructible_expr (to, from);
|
||||
|
||||
if (expr == error_mark_node)
|
||||
return false;
|
||||
tree nt = cp_walk_tree_without_duplicates (&expr, check_nontriv, NULL);
|
||||
return !nt;
|
||||
}
|
||||
|
||||
/* Subroutine of synthesized_method_walk. Update SPEC_P, TRIVIAL_P and
|
||||
DELETED_P or give an error message MSG with argument ARG. */
|
||||
|
||||
|
@ -4490,6 +4490,8 @@ cp_parser_primary_expression (cp_parser *parser,
|
||||
case RID_IS_POLYMORPHIC:
|
||||
case RID_IS_STD_LAYOUT:
|
||||
case RID_IS_TRIVIAL:
|
||||
case RID_IS_TRIVIALLY_ASSIGNABLE:
|
||||
case RID_IS_TRIVIALLY_CONSTRUCTIBLE:
|
||||
case RID_IS_TRIVIALLY_COPYABLE:
|
||||
case RID_IS_UNION:
|
||||
return cp_parser_trait_expr (parser, token->keyword);
|
||||
@ -8664,6 +8666,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
|
||||
cp_trait_kind kind;
|
||||
tree type1, type2 = NULL_TREE;
|
||||
bool binary = false;
|
||||
bool variadic = false;
|
||||
|
||||
switch (keyword)
|
||||
{
|
||||
@ -8725,6 +8728,14 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
|
||||
case RID_IS_TRIVIAL:
|
||||
kind = CPTK_IS_TRIVIAL;
|
||||
break;
|
||||
case RID_IS_TRIVIALLY_ASSIGNABLE:
|
||||
kind = CPTK_IS_TRIVIALLY_ASSIGNABLE;
|
||||
binary = true;
|
||||
break;
|
||||
case RID_IS_TRIVIALLY_CONSTRUCTIBLE:
|
||||
kind = CPTK_IS_TRIVIALLY_CONSTRUCTIBLE;
|
||||
variadic = true;
|
||||
break;
|
||||
case RID_IS_TRIVIALLY_COPYABLE:
|
||||
kind = CPTK_IS_TRIVIALLY_COPYABLE;
|
||||
break;
|
||||
@ -8763,6 +8774,17 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
|
||||
if (type2 == error_mark_node)
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (variadic)
|
||||
{
|
||||
while (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
|
||||
{
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
tree elt = cp_parser_type_id (parser);
|
||||
if (elt == error_mark_node)
|
||||
return error_mark_node;
|
||||
type2 = tree_cons (NULL_TREE, elt, type2);
|
||||
}
|
||||
}
|
||||
|
||||
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
||||
|
||||
|
@ -7379,6 +7379,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
|
||||
case CPTK_IS_TRIVIAL:
|
||||
return (trivial_type_p (type1));
|
||||
|
||||
case CPTK_IS_TRIVIALLY_ASSIGNABLE:
|
||||
return is_trivially_xible (MODIFY_EXPR, type1, type2);
|
||||
|
||||
case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
|
||||
return is_trivially_xible (INIT_EXPR, type1, type2);
|
||||
|
||||
case CPTK_IS_TRIVIALLY_COPYABLE:
|
||||
return (trivially_copyable_p (type1));
|
||||
|
||||
@ -7392,19 +7398,26 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
|
||||
}
|
||||
|
||||
/* If TYPE is an array of unknown bound, or (possibly cv-qualified)
|
||||
void, or a complete type, returns it, otherwise NULL_TREE. */
|
||||
void, or a complete type, returns true, otherwise false. */
|
||||
|
||||
static tree
|
||||
static bool
|
||||
check_trait_type (tree type)
|
||||
{
|
||||
if (type == NULL_TREE)
|
||||
return true;
|
||||
|
||||
if (TREE_CODE (type) == TREE_LIST)
|
||||
return (check_trait_type (TREE_VALUE (type))
|
||||
&& check_trait_type (TREE_CHAIN (type)));
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
|
||||
&& COMPLETE_TYPE_P (TREE_TYPE (type)))
|
||||
return type;
|
||||
return true;
|
||||
|
||||
if (VOID_TYPE_P (type))
|
||||
return type;
|
||||
return true;
|
||||
|
||||
return complete_type_or_else (strip_array_types (type), NULL_TREE);
|
||||
return !!complete_type_or_else (strip_array_types (type), NULL_TREE);
|
||||
}
|
||||
|
||||
/* Process a trait expression. */
|
||||
@ -7413,8 +7426,7 @@ tree
|
||||
finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
|
||||
{
|
||||
if (type1 == error_mark_node
|
||||
|| ((kind == CPTK_IS_BASE_OF)
|
||||
&& type2 == error_mark_node))
|
||||
|| type2 == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if (processing_template_decl)
|
||||
@ -7450,6 +7462,13 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
|
||||
return error_mark_node;
|
||||
break;
|
||||
|
||||
case CPTK_IS_TRIVIALLY_ASSIGNABLE:
|
||||
case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
|
||||
if (!check_trait_type (type1)
|
||||
|| !check_trait_type (type2))
|
||||
return error_mark_node;
|
||||
break;
|
||||
|
||||
case CPTK_IS_BASE_OF:
|
||||
if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
|
||||
&& !same_type_ignoring_top_level_qualifiers_p (type1, type2)
|
||||
|
35
gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C
Normal file
35
gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C
Normal file
@ -0,0 +1,35 @@
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct A { };
|
||||
struct B { B(); operator int(); };
|
||||
struct C {
|
||||
C() = default;
|
||||
C(const C&);
|
||||
C(C&&) = default;
|
||||
C& operator=(C&&);
|
||||
C& operator= (const C&) = default;
|
||||
};
|
||||
struct D { ~D() {} };
|
||||
|
||||
#define SA(X) static_assert((X),#X)
|
||||
|
||||
SA(__is_trivially_constructible(A));
|
||||
SA(__is_trivially_constructible(A,A));
|
||||
SA(!__is_trivially_constructible(B));
|
||||
SA(__is_trivially_constructible(B,B));
|
||||
|
||||
SA(!__is_trivially_constructible(A,B));
|
||||
SA(!__is_trivially_constructible(B,A));
|
||||
|
||||
SA(__is_trivially_constructible(C));
|
||||
SA(__is_trivially_constructible(C,C));
|
||||
SA(!__is_trivially_constructible(C,C&));
|
||||
SA(__is_trivially_assignable(C,C&));
|
||||
SA(!__is_trivially_assignable(C,C));
|
||||
SA(!__is_trivially_assignable(C,C&&));
|
||||
|
||||
SA(__is_trivially_constructible(int,int));
|
||||
SA(__is_trivially_constructible(int,double));
|
||||
SA(!__is_trivially_constructible(int,B));
|
||||
|
||||
SA(!__is_trivially_constructible(D));
|
Loading…
Reference in New Issue
Block a user