From patchwork Mon Apr 25 21:53:34 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 92814 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 5F90E1007D1 for ; Tue, 26 Apr 2011 07:53:53 +1000 (EST) Received: (qmail 24511 invoked by alias); 25 Apr 2011 21:53:51 -0000 Received: (qmail 24502 invoked by uid 22791); 25 Apr 2011 21:53:50 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, 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; Mon, 25 Apr 2011 21:53:35 +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 p3PLrZg1012325 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 25 Apr 2011 17:53:35 -0400 Received: from [127.0.0.1] (ovpn-113-113.phx2.redhat.com [10.3.113.113]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p3PLrYxF008145 for ; Mon, 25 Apr 2011 17:53:34 -0400 Message-ID: <4DB5ED5E.1040700@redhat.com> Date: Mon, 25 Apr 2011 17:53:34 -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++ PATCH for c++/48707 (c++0x ice on initialization in template) 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 C++0x we can have an initializer that is potentially constant and yet still type-dependent if it involves a call, so we need to handle that. For 4.7 I'm explicitly testing for type-dependency; for 4.6 I've made a smaller change to make value_dependent_expression_p return true for type-dependent expressions as well. Tested x86_64-pc-linux-gnu, applied to trunk and 4.6. commit 8d43d26b5dc0392f91ad6015955b92b1905e64ce Author: Jason Merrill Date: Sat Apr 23 23:18:00 2011 -0400 PR c++/48707 * decl.c (type_dependent_init_p): New. (cp_finish_decl): Check it. * pt.c (any_type_dependent_elements_p): New. * cp-tree.h: Declare it. commit 6b978a4d2e33771d8fd95f39a301f8df180ac98c Author: Jason Merrill Date: Mon Apr 25 16:44:03 2011 -0400 PR c++/48707 * pt.c (value_dependent_expression_p): Handle type-dependent expression. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ed48203..fc5177d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18068,6 +18068,11 @@ value_dependent_expression_p (tree expression) if (DECL_P (expression) && type_dependent_expression_p (expression)) return true; + /* We shouldn't have gotten here for a type-dependent expression, but + let's handle it properly anyway. */ + if (TREE_TYPE (expression) == NULL_TREE) + return true; + switch (TREE_CODE (expression)) { case IDENTIFIER_NODE: diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C b/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C new file mode 100644 index 0000000..25354b3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C @@ -0,0 +1,14 @@ +// PR c++/48707 +// { dg-options -std=c++0x } + +struct A { + static int a(); +}; + +template +struct B: A { + static int const b; +}; + +template +int const B::b=B::a(); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6a612e9..fd477a4 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5106,6 +5106,7 @@ extern bool dependent_template_p (tree); extern bool dependent_template_id_p (tree, tree); extern bool type_dependent_expression_p (tree); extern bool any_type_dependent_arguments_p (const VEC(tree,gc) *); +extern bool any_type_dependent_elements_p (const_tree); extern bool type_dependent_expression_p_push (tree); extern bool value_dependent_expression_p (tree); extern bool any_value_dependent_elements_p (const_tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d97ccf3..92e0d48 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5701,6 +5701,36 @@ initialize_artificial_var (tree decl, VEC(constructor_elt,gc) *v) } /* INIT is the initializer for a variable, as represented by the + parser. Returns true iff INIT is type-dependent. */ + +static bool +type_dependent_init_p (tree init) +{ + if (TREE_CODE (init) == TREE_LIST) + /* A parenthesized initializer, e.g.: int i (3, 2); ? */ + return any_type_dependent_elements_p (init); + else if (TREE_CODE (init) == CONSTRUCTOR) + /* A brace-enclosed initializer, e.g.: int i = { 3 }; ? */ + { + VEC(constructor_elt, gc) *elts; + size_t nelts; + size_t i; + + elts = CONSTRUCTOR_ELTS (init); + nelts = VEC_length (constructor_elt, elts); + for (i = 0; i < nelts; ++i) + if (type_dependent_init_p (VEC_index (constructor_elt, + elts, i)->value)) + return true; + } + else + /* It must be a simple expression, e.g., int i = 3; */ + return type_dependent_expression_p (init); + + return false; +} + +/* INIT is the initializer for a variable, as represented by the parser. Returns true iff INIT is value-dependent. */ static bool @@ -5876,19 +5906,25 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, template is instantiated. But, if DECL is a variable constant then it can be used in future constant expressions, so its value must be available. */ - if (init - && init_const_expr_p - && !type_dependent_p - && decl_maybe_constant_var_p (decl) - && !value_dependent_init_p (init)) + + if (TREE_CODE (decl) != VAR_DECL || dependent_type_p (type)) + /* We can't do anything if the decl has dependent type. */; + else if (init + && init_const_expr_p + && !type_dependent_p + && decl_maybe_constant_var_p (decl) + && !type_dependent_init_p (init) + && !value_dependent_init_p (init)) { + /* This variable seems to be a non-dependent constant, so process + its initializer. If check_initializer returns non-null the + initialization wasn't constant after all. */ tree init_code = check_initializer (decl, init, flags, &cleanup); if (init_code == NULL_TREE) init = NULL_TREE; } - else if (TREE_CODE (decl) == VAR_DECL - && !DECL_PRETTY_FUNCTION_P (decl) - && !type_dependent_p) + else if (!DECL_PRETTY_FUNCTION_P (decl)) + /* Deduce array size even if the initializer is dependent. */ maybe_deduce_size_from_array_init (decl, init); if (init) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index cb8ebfd..6765931 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18457,6 +18457,19 @@ any_type_dependent_arguments_p (const VEC(tree,gc) *args) } /* Returns TRUE if LIST (a TREE_LIST whose TREE_VALUEs are + expressions) contains any type-dependent expressions. */ + +bool +any_type_dependent_elements_p (const_tree list) +{ + for (; list; list = TREE_CHAIN (list)) + if (value_dependent_expression_p (TREE_VALUE (list))) + return true; + + return false; +} + +/* Returns TRUE if LIST (a TREE_LIST whose TREE_VALUEs are expressions) contains any value-dependent expressions. */ bool diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C b/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C new file mode 100644 index 0000000..25354b3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C @@ -0,0 +1,14 @@ +// PR c++/48707 +// { dg-options -std=c++0x } + +struct A { + static int a(); +}; + +template +struct B: A { + static int const b; +}; + +template +int const B::b=B::a();