From patchwork Mon Sep 5 04:29:17 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 113305 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]) by ozlabs.org (Postfix) with SMTP id 33723B6F71 for ; Mon, 5 Sep 2011 14:29:43 +1000 (EST) Received: (qmail 15462 invoked by alias); 5 Sep 2011 04:29:39 -0000 Received: (qmail 15161 invoked by uid 22791); 5 Sep 2011 04:29:36 -0000 X-SWARE-Spam-Status: No, hits=-6.6 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_FN, TW_SF X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 05 Sep 2011 04:29:19 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p854TJCA030961 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 5 Sep 2011 00:29:19 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p854TI1e016038 for ; Mon, 5 Sep 2011 00:29:19 -0400 Received: from [0.0.0.0] (ovpn-113-26.phx2.redhat.com [10.3.113.26]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id p854THcF000665 for ; Mon, 5 Sep 2011 00:29:18 -0400 Message-ID: <4E64501D.5050806@redhat.com> Date: Mon, 05 Sep 2011 00:29:17 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/20110817 Thunderbird/6.0 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor) 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 At the Bloomington C++ meeting we discussed some issues with the constexpr specification that the clang team encountered while trying to implement it. Among the issues was a problem that also came up recently for us as BZ 50248: if the constexpr-ness of a template instantiation depends on its body, we need to instantiate it in order to decide whether or not an implicitly-declared function that uses it is constexpr. The resolution of DR 1358 is that an instantiation of a constexpr template is constexpr even if it can never produce a constant expression. The second patch is related to DR 1360, where the clang team was complaining that deciding whether or not a class is literal requires the implicit declaration of the default constructor, which they would like to do lazily. We seem to have agreed that it can be avoided in the cases where doing such is useful, but while looking at this I noticed a bug in our handling of this stuff: the function synthesized_default_constructor_is_constexpr was only right for trivial constructors. So now I've renamed it accordingly, and force the implicit declaration for the non-trivial case. Tested x86_64-pc-linux-gnu, applying to trunk. commit 2f4a14c2ce37bbba87e45977c1314ab7984baf72 Author: Jason Merrill Date: Fri Aug 19 09:21:45 2011 -0400 * class.c (trivial_default_constructor_is_constexpr): Rename from synthesized_default_constructor_is_constexpr. (type_has_constexpr_default_constructor): Adjust. (add_implicitly_declared_members): Call it instead. (explain_non_literal_class): Explain about non-constexpr default ctor. * cp-tree.h: Adjust. * method.c (synthesized_method_walk): Adjust. * semantics.c (explain_invalid_constexpr_fn): Handle defaulted functions, too. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 2a4bc77..a4a7468 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2726,7 +2726,8 @@ add_implicitly_declared_members (tree t, CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1; if (cxx_dialect >= cxx0x) TYPE_HAS_CONSTEXPR_CTOR (t) - = synthesized_default_constructor_is_constexpr (t); + /* This might force the declaration. */ + = type_has_constexpr_default_constructor (t); } /* [class.ctor] @@ -4355,15 +4356,15 @@ type_has_user_provided_default_constructor (tree t) return false; } -/* Returns true iff for class T, a synthesized default constructor +/* Returns true iff for class T, a trivial synthesized default constructor would be constexpr. */ bool -synthesized_default_constructor_is_constexpr (tree t) +trivial_default_constructor_is_constexpr (tree t) { - /* A defaulted default constructor is constexpr + /* A defaulted trivial default constructor is constexpr if there is nothing to initialize. */ - /* FIXME adjust for non-static data member initializers. */ + gcc_assert (!TYPE_HAS_COMPLEX_DFLT (t)); return is_really_empty_class (t); } @@ -4381,7 +4382,12 @@ type_has_constexpr_default_constructor (tree t) return false; } if (CLASSTYPE_LAZY_DEFAULT_CTOR (t)) - return synthesized_default_constructor_is_constexpr (t); + { + if (!TYPE_HAS_COMPLEX_DFLT (t)) + return trivial_default_constructor_is_constexpr (t); + /* Non-trivial, we need to check subobject constructors. */ + lazily_declare_fn (sfk_constructor, t); + } fns = locate_ctor (t); return (fns && DECL_DECLARED_CONSTEXPR_P (fns)); } @@ -4608,9 +4614,14 @@ explain_non_literal_class (tree t) else if (CLASSTYPE_NON_AGGREGATE (t) && !TYPE_HAS_TRIVIAL_DFLT (t) && !TYPE_HAS_CONSTEXPR_CTOR (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); + { + 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)) + explain_invalid_constexpr_fn (locate_ctor (t)); + } else { tree binfo, base_binfo, field; int i; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d18599b..cf6c056 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4823,7 +4823,7 @@ 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 synthesized_default_constructor_is_constexpr (tree); +extern bool trivial_default_constructor_is_constexpr (tree); extern bool type_has_constexpr_default_constructor (tree); extern bool type_has_virtual_destructor (tree); extern bool type_has_move_constructor (tree); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 74a3bdb..5b24f8f 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1187,7 +1187,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, && (!copy_arg_p || cxx_dialect < cxx0x)) { if (constexpr_p && sfk == sfk_constructor) - *constexpr_p = synthesized_default_constructor_is_constexpr (ctype); + *constexpr_p = trivial_default_constructor_is_constexpr (ctype); return; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index fd96d70..bdc4cf2 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5881,8 +5881,9 @@ explain_invalid_constexpr_fn (tree fun) static struct pointer_set_t *diagnosed; tree body; location_t save_loc; - /* Only diagnose instantiations of constexpr templates. */ - if (!is_instantiation_of_constexpr (fun)) + /* Only diagnose defaulted functions or instantiations. */ + if (!DECL_DEFAULTED_FN (fun) + && !is_instantiation_of_constexpr (fun)) return; if (diagnosed == NULL) diagnosed = pointer_set_create (); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C new file mode 100644 index 0000000..d3868b5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C @@ -0,0 +1,12 @@ +// { dg-options -std=c++0x } + +struct A { + int i; + constexpr A():i(42) { }; +}; +struct B: A { }; +constexpr int f(B b) { return b.i; } + +struct C { C(); }; // { dg-message "calls non-constexpr" } +struct D: C { }; // { dg-message "no constexpr constructor" } +constexpr int g(D d) { return 42; } // { dg-error "invalid type" }