From patchwork Wed Oct 1 17:20:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 395620 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 877BD140174 for ; Thu, 2 Oct 2014 03:21:04 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:references :in-reply-to:content-type; q=dns; s=default; b=tCanlNp+/PbrhR0db mGK6f9whVujJ6iUSKhyWNKmIyMRCWDb+qgI663x+bn0OpXs3SXwHqoIKKHSieLBB M59Q1roloDWeTU06JI/RMnPdF6dGaiW04dM8PWBWOiiZ6C0t7fB4ThlAyJqJwFnl FhKgfR5N0IenKZexTKPa6tncwo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:references :in-reply-to:content-type; s=default; bh=ZsWKGvnRyqwJsVNxO/gAKCE KzYM=; b=P7WfYE/fHXNy8fM+q6fMa7kiRWavRkw+7nmwqbqkFi+DUSbpPk1JcZ+ Ea5f3+PCg8wUAQ5OhdrNCsxHTQz2Owd0iNfjhcb9E14/AvhvxDhZlK+nXPpbu4hZ sc3lmslY4xbwBDLrFTT4IY5nhdHv/5GhY1g/WRE4oo2dDAQUQGSE= Received: (qmail 28210 invoked by alias); 1 Oct 2014 17:20:54 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 28191 invoked by uid 89); 1 Oct 2014 17:20:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.1 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 01 Oct 2014 17:20:52 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s91HKotO008961 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 1 Oct 2014 13:20:50 -0400 Received: from [10.10.116.26] ([10.10.116.26]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s91HKmvR028074; Wed, 1 Oct 2014 13:20:49 -0400 Message-ID: <542C37ED.5010902@redhat.com> Date: Wed, 01 Oct 2014 13:20:45 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.1.1 MIME-Version: 1.0 To: Ville Voutilainen , Paolo Carlini , "gcc-patches@gcc.gnu.org" , libstdc++@gcc.gnu.org Subject: Re: C++ PATCHes to add __is_trivially_* References: In-Reply-To: On 09/30/2014 06:48 PM, Ville Voutilainen wrote: >>> Ville asked for help with the necessary compiler intrinsics for the is_trivially_* >>C++11 library traits. The first patch cleans up a few oddities I noticed with the >> Great. I think this can be as well marked as PR c++/26099. > > There's also PR c++/63362. > > The intrinsics still fail to support certain variadic cases, such as > > template void bar() { > static_assert(__is_trivially_constructible(T, Args...), ""); > } Here are two more patches: the first fixes trivial_fn_p for a defaulted default constructor overloaded with a template default constructor, and the second fixes the variadic case above. commit 68a53de3f12b1d2adacf39d59836a558cc257759 Author: Jason Merrill Date: Tue Sep 30 17:24:13 2014 -0400 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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 8f1b91a..3c8b338 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 acf5768..12ac30a 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 b2b9063..14ec837 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 d26a432..7856dd8 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 f0ca9b9..6851fe9 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 0000000..4e0a657 --- /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)); commit 591e70a3906af599160ec59287f20ed20b8082ca Author: Jason Merrill Date: Wed Oct 1 13:00:49 2014 -0400 PR c++/63362 * method.c (constructible_expr): Handle value-init of non-class. * parser.c (cp_parser_trait_expr): Allow pack expansion. * pt.c (tsubst_copy_and_build): Handle pack expansion. diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 9a2bd0f..8828986 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1077,7 +1077,9 @@ constructible_expr (tree to, tree from) } else { - if (TREE_CHAIN (from)) + if (from == NULL_TREE) + return build_value_init (to, tf_none); + 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, diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index e4aaf53..01b2fad 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -8780,6 +8780,11 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) { cp_lexer_consume_token (parser->lexer); tree elt = cp_parser_type_id (parser); + if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) + { + cp_lexer_consume_token (parser->lexer); + elt = make_pack_expansion (elt); + } if (elt == error_mark_node) return error_mark_node; type2 = tree_cons (NULL_TREE, elt, type2); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9dd61f3..f03e74c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -15487,7 +15487,9 @@ tsubst_copy_and_build (tree t, complain, in_decl); tree type2 = TRAIT_EXPR_TYPE2 (t); - if (type2) + if (type2 && TREE_CODE (type2) == TREE_LIST) + type2 = RECUR (type2); + else if (type2) type2 = tsubst (type2, args, complain, in_decl); RETURN (finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2)); diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible3.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible3.C new file mode 100644 index 0000000..02a678a --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible3.C @@ -0,0 +1,8 @@ +// { dg-do compile { target c++11 } } + +template void bar() { + static_assert(__is_trivially_constructible(T, Args...), ""); +} + +template void bar(); +template void bar();