From a710f1f83caee6e647bebf6b45743b276ac55cbf Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 1 Oct 2014 13:21:01 -0400 Subject: [PATCH] re PR c++/63362 (The c++11 triviality-traits need front-end help) PR c++/63362 * class.c (type_has_non_user_provided_default_constructor): Rename from type_has_user_provided_default_constructor, reverse sense. (default_init_uninitialized_part, explain_non_literal_class): Adjust. (check_bases_and_members): Set TYPE_HAS_COMPLEX_DFLT. * call.c (build_new_method_call_1): Adjust. * cp-tree.h: Adjust. * decl.c (grok_special_member_properties): Don't set TYPE_HAS_COMPLEX_DFLT. * init.c (build_value_init_noctor): Don't use type_has_user_provided_default_constructor. From-SVN: r215771 --- gcc/cp/ChangeLog | 14 +++++++++++++ gcc/cp/call.c | 2 +- gcc/cp/class.c | 24 +++++++++++++++------- gcc/cp/cp-tree.h | 4 ++-- gcc/cp/decl.c | 6 +----- gcc/cp/init.c | 14 ++++++++----- .../g++.dg/ext/is_trivially_constructible2.C | 15 ++++++++++++++ 7 files changed, 59 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/is_trivially_constructible2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2fedd372a48..9a9fc342569 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2014-10-01 Jason Merrill + + PR c++/63362 + * class.c (type_has_non_user_provided_default_constructor): Rename + from type_has_user_provided_default_constructor, reverse sense. + (default_init_uninitialized_part, explain_non_literal_class): Adjust. + (check_bases_and_members): Set TYPE_HAS_COMPLEX_DFLT. + * call.c (build_new_method_call_1): Adjust. + * cp-tree.h: Adjust. + * decl.c (grok_special_member_properties): Don't set + TYPE_HAS_COMPLEX_DFLT. + * init.c (build_value_init_noctor): Don't use + type_has_user_provided_default_constructor. + 2014-09-30 Jason Merrill * cp-tree.h (cp_trait_kind): Add CPTK_IS_TRIVIALLY_ASSIGNABLE and diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 8f1b91a4f16..3c8b338382a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7941,7 +7941,7 @@ build_new_method_call_1 (tree instance, tree fns, vec **args, && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype) /* For a user-provided default constructor, use the normal mechanisms so that protected access works. */ - && !type_has_user_provided_default_constructor (basetype) + && type_has_non_user_provided_default_constructor (basetype) && !processing_template_decl) init = build_value_init (basetype, complain); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index acf5768b7d3..12ac30a84a8 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4937,21 +4937,25 @@ type_has_user_provided_constructor (tree t) return false; } -/* Returns true iff class T has a user-provided default constructor. */ +/* Returns true iff class T has a non-user-provided (i.e. implicitly + declared or explicitly defaulted in the class body) default + constructor. */ bool -type_has_user_provided_default_constructor (tree t) +type_has_non_user_provided_default_constructor (tree t) { tree fns; - if (!TYPE_HAS_USER_CONSTRUCTOR (t)) + if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (t)) return false; + if (CLASSTYPE_LAZY_DEFAULT_CTOR (t)) + return true; for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); if (TREE_CODE (fn) == FUNCTION_DECL - && user_provided_p (fn) + && !user_provided_p (fn) && sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (fn))) return true; } @@ -5009,7 +5013,7 @@ default_init_uninitialized_part (tree type) type = strip_array_types (type); if (!CLASS_TYPE_P (type)) return type; - if (type_has_user_provided_default_constructor (type)) + if (!type_has_non_user_provided_default_constructor (type)) return NULL_TREE; for (binfo = TYPE_BINFO (type), i = 0; BINFO_BASE_ITERATE (binfo, i, t); ++i) @@ -5383,8 +5387,7 @@ explain_non_literal_class (tree t) inform (0, " %q+T is not an aggregate, does not have a trivial " "default constructor, and has no constexpr constructor that " "is not a copy or move constructor", t); - if (TYPE_HAS_DEFAULT_CONSTRUCTOR (t) - && !type_has_user_provided_default_constructor (t)) + if (type_has_non_user_provided_default_constructor (t)) { /* Note that we can't simply call locate_ctor because when the constructor is deleted it just returns NULL_TREE. */ @@ -5528,6 +5531,13 @@ check_bases_and_members (tree t) TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) |= TYPE_CONTAINS_VPTR_P (t); TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t); + /* If the only explicitly declared default constructor is user-provided, + set TYPE_HAS_COMPLEX_DFLT. */ + if (!TYPE_HAS_COMPLEX_DFLT (t) + && TYPE_HAS_DEFAULT_CONSTRUCTOR (t) + && !type_has_non_user_provided_default_constructor (t)) + TYPE_HAS_COMPLEX_DFLT (t) = true; + /* Warn if a public base of a polymorphic type has an accessible non-virtual destructor. It is only now that we know the class is polymorphic. Although a polymorphic base will have a already diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b2b9063a365..14ec837dc9c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3484,7 +3484,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) /* Nonzero if there is a non-trivial X::X(X&&) for this class. */ #define TYPE_HAS_COMPLEX_MOVE_CTOR(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_move_ctor) -/* Nonzero if there is a non-trivial default constructor for this class. */ +/* Nonzero if there is no trivial default constructor for this class. */ #define TYPE_HAS_COMPLEX_DFLT(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_dflt) /* Nonzero if TYPE has a trivial destructor. From [class.dtor]: @@ -5195,7 +5195,7 @@ extern bool type_has_user_nondefault_constructor (tree); extern tree in_class_defaulted_default_constructor (tree); extern bool user_provided_p (tree); extern bool type_has_user_provided_constructor (tree); -extern bool type_has_user_provided_default_constructor (tree); +extern bool type_has_non_user_provided_default_constructor (tree); extern bool vbase_has_user_provided_move_assign (tree); extern tree default_init_uninitialized_part (tree); extern bool trivial_default_constructor_is_constexpr (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d26a432bf6e..7856dd836ed 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -11476,11 +11476,7 @@ grok_special_member_properties (tree decl) TYPE_HAS_CONST_COPY_CTOR (class_type) = 1; } else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl))) - { - TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1; - if (user_provided_p (decl)) - TYPE_HAS_COMPLEX_DFLT (class_type) = 1; - } + TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1; else if (move_fn_p (decl) && user_provided_p (decl)) TYPE_HAS_COMPLEX_MOVE_CTOR (class_type) = 1; else if (is_list_ctor (decl)) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index f0ca9b9a396..6851fe9dc7e 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -343,13 +343,17 @@ build_value_init (tree type, tsubst_flags_t complain) if (CLASS_TYPE_P (type) && type_build_ctor_call (type)) { - tree ctor = build_aggr_init_expr - (type, + tree ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, NULL, type, LOOKUP_NORMAL, - complain)); - if (ctor == error_mark_node - || type_has_user_provided_default_constructor (type)) + complain); + if (ctor == error_mark_node) + return ctor; + tree fn = NULL_TREE; + if (TREE_CODE (ctor) == CALL_EXPR) + fn = get_callee_fndecl (ctor); + ctor = build_aggr_init_expr (type, ctor); + if (fn && user_provided_p (fn)) return ctor; else if (TYPE_HAS_COMPLEX_DFLT (type)) { diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible2.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible2.C new file mode 100644 index 00000000000..4e0a657eaff --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible2.C @@ -0,0 +1,15 @@ +// { dg-do compile { target c++11 } } + +struct X { + X() = default; + template X(U...); +}; + +struct Y { + template Y(U...); +}; + +#define SA(X) static_assert((X),#X) + +SA(__is_trivially_constructible(X)); +SA(!__is_trivially_constructible(Y)); -- 2.11.4.GIT