From patchwork Tue Mar 29 13:26:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 88767 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 AB049B6EF7 for ; Wed, 30 Mar 2011 00:27:14 +1100 (EST) Received: (qmail 22120 invoked by alias); 29 Mar 2011 13:27:11 -0000 Received: (qmail 22073 invoked by uid 22791); 29 Mar 2011 13:27:09 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_CX, T_RP_MATCHES_RCVD 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; Tue, 29 Mar 2011 13:26:58 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p2TDQwGM029279 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 29 Mar 2011 09:26:58 -0400 Received: from [127.0.0.1] ([10.3.113.2]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p2TDQu2s026500 for ; Tue, 29 Mar 2011 09:26:57 -0400 Message-ID: <4D91DE20.6030304@redhat.com> Date: Tue, 29 Mar 2011 09:26:56 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.15) Gecko/20110307 Fedora/3.1.9-0.39.b3pre.fc14 Lightning/1.0b2 Thunderbird/3.1.9 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCHes for c++/48296 (constexpr function returning current class) 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 In 48296, the problem was that we were checking the parameter and return types for literality too soon; we don't know whether the current class is literal until we're done defining it. So let's be more patient about checking. The second patch changes the validation errors to point at the locus of the function declaration in question, which improves their usefulness. Tested x86_64-pc-linux-gnu, applying to trunk and 4.6. commit ff8fcc903da4c162cdc99f5f967767148fe94d34 Author: Jason Merrill Date: Tue Mar 29 00:45:42 2011 -0400 PR c++/48296 * decl.c (cp_finish_decl): Defer validation of constexpr member functions. * class.c (finalize_literal_type_property): Validate them here. * semantics.c (is_valid_constexpr_fn): Don't check completeness. commit 055a6dbed418d3ab63420309433d8d7a9ddf172c Author: Jason Merrill Date: Mon Mar 28 19:49:41 2011 -0400 * semantics.c (is_valid_constexpr_fn): Specify input location. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 6906c1b..da8c016 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5338,8 +5338,8 @@ is_valid_constexpr_fn (tree fun, bool complain) { ret = false; if (complain) - error ("invalid type for parameter %q#D of constexpr function", - parm); + error ("invalid type for parameter %d of constexpr " + "function %q+#D", DECL_PARM_INDEX (parm), fun); } if (!DECL_CONSTRUCTOR_P (fun)) @@ -5349,7 +5349,7 @@ is_valid_constexpr_fn (tree fun, bool complain) { ret = false; if (complain) - error ("invalid return type %qT of constexpr function %qD", + error ("invalid return type %qT of constexpr function %q+D", rettype, fun); } @@ -5359,7 +5359,7 @@ is_valid_constexpr_fn (tree fun, bool complain) { ret = false; if (complain) - error ("enclosing class of %q#D is not a literal type", fun); + error ("enclosing class of %q+#D is not a literal type", fun); } } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C index a3706d6..183d3f7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C @@ -1,12 +1,11 @@ // Test that we explain why a template instantiation isn't constexpr // { dg-options -std=c++0x } -// { dg-prune-output "not a constexpr function" } template struct A { T t; - constexpr int f() { return 42; } + constexpr int f() { return 42; } // { dg-error "enclosing class" } }; struct B { B(); operator int(); }; @@ -14,8 +13,8 @@ struct B { B(); operator int(); }; constexpr A ai = { 42 }; constexpr int i = ai.f(); -constexpr int b = A().f(); // { dg-error "enclosing class" } +constexpr int b = A().f(); // { dg-error "not a constexpr function" } template -constexpr int f (T t) { return 42; } -constexpr int x = f(B()); // { dg-error "parameter" } +constexpr int f (T t) { return 42; } // { dg-error "parameter" } +constexpr int x = f(B()); // { dg-error "constexpr function" } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index adae51f..24b8a31 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4549,6 +4549,8 @@ type_requires_array_cookie (tree type) static void finalize_literal_type_property (tree t) { + tree fn; + if (cxx_dialect < cxx0x || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) /* FIXME These constraints seem unnecessary; remove from standard. @@ -4559,18 +4561,10 @@ finalize_literal_type_property (tree t) && !TYPE_HAS_CONSTEXPR_CTOR (t)) CLASSTYPE_LITERAL_P (t) = false; - if (!CLASSTYPE_LITERAL_P (t) && !CLASSTYPE_TEMPLATE_INSTANTIATION (t)) - { - tree fn; - for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) - if (DECL_DECLARED_CONSTEXPR_P (fn) - && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn) - && !DECL_CONSTRUCTOR_P (fn)) - { - error ("enclosing class of %q+D is not a literal type", fn); - DECL_DECLARED_CONSTEXPR_P (fn) = false; - } - } + for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) + if (DECL_DECLARED_CONSTEXPR_P (fn) + && TREE_CODE (fn) != TEMPLATE_DECL) + validate_constexpr_fundecl (fn); } /* Check the validity of the bases and members declared in T. Add any diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 895527c..16ccfaf 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5794,7 +5794,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, } } - if (TREE_CODE (decl) == FUNCTION_DECL) + if (TREE_CODE (decl) == FUNCTION_DECL + /* For members, defer until finalize_literal_type_property. */ + && (!DECL_CLASS_SCOPE_P (decl) + || !TYPE_BEING_DEFINED (DECL_CONTEXT (decl)))) validate_constexpr_fundecl (decl); else if (!ensure_literal_type_for_constexpr_object (decl)) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index da8c016..f1c3d9a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5354,8 +5354,7 @@ is_valid_constexpr_fn (tree fun, bool complain) } if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun) - && COMPLETE_TYPE_P (DECL_CONTEXT (fun)) - && !valid_type_in_constexpr_fundecl_p (DECL_CONTEXT (fun))) + && !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun))) { ret = false; if (complain) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C new file mode 100644 index 0000000..4646f82 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C @@ -0,0 +1,18 @@ +// PR c++/48296 +// { dg-options -std=c++0x } + +struct X +{ + constexpr X() { } + constexpr X f(X x) { return x; } + constexpr X g(X x); +}; + +constexpr X X::g(X x) { return x; } + +struct Y +{ + Y() { } + constexpr Y f(Y y); // { dg-error "constexpr" } + static constexpr Y g(Y y); // { dg-error "constexpr" } +};