From patchwork Wed Apr 20 19:36:08 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 92291 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 F27DDB6EDD for ; Thu, 21 Apr 2011 05:36:27 +1000 (EST) Received: (qmail 31608 invoked by alias); 20 Apr 2011 19:36:25 -0000 Received: (qmail 31454 invoked by uid 22791); 20 Apr 2011 19:36:24 -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; Wed, 20 Apr 2011 19:36:10 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p3KJa9id007831 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 20 Apr 2011 15:36:09 -0400 Received: from [127.0.0.1] (ovpn-113-102.phx2.redhat.com [10.3.113.102]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p3KJa92N024818 for ; Wed, 20 Apr 2011 15:36:09 -0400 Message-ID: <4DAF35A8.9010803@redhat.com> Date: Wed, 20 Apr 2011 12:36:08 -0700 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++/48657 (rejects-valid with local variable used as non-type template argument) 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 The problem in this testcase was that we were recognizing a local const variable with a constant initializer as a constant expression, but we weren't doing the necessary adjustments to convert the initializer to the type of the variable. But some of the other bits of cp_finish_decl caused problems for variables with function scope. After some investigation, it seemed to me that the only part of cp_finish_decl that we really want for constants in templates is the initializer processing, so rather than mess with clearing processing_template_decl and going through all the other pieces, we can just call check_initializer directly and then be done. For 4.6 I made a smaller change that only affects local variables. Tested x86_64-pc-linux-gnu, applying to trunk and 4.6. commit 56ee3cf091b9b349ddbcdc8afb62e4ec4cf0eae0 Author: Jason Merrill Date: Tue Apr 19 23:25:21 2011 -0700 PR c++/48657 * decl.c (cp_finish_decl): Simplify template handling. commit a4b9191f458ee8c6a2555b83daacd158520244eb Author: Jason Merrill Date: Wed Apr 20 12:05:28 2011 -0700 PR c++/48657 * decl.c (cp_finish_decl): Handle non-member constant variables in templates, too. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 41beef3..61b57ea 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5862,11 +5862,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, then it can be used in future constant expressions, so its value must be available. */ if (!(init - && DECL_CLASS_SCOPE_P (decl) - /* We just set TREE_CONSTANT appropriately; see above. */ - && TREE_CONSTANT (decl) + && init_const_expr_p && !type_dependent_p - /* FIXME non-value-dependent constant expression */ + && decl_maybe_constant_var_p (decl) && !value_dependent_init_p (init))) { if (init) @@ -5878,6 +5876,14 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, goto finish_end; } + if (!DECL_CLASS_SCOPE_P (decl)) + { + tree init_code = check_initializer (decl, init, flags, &cleanup); + if (init_code) + DECL_INITIAL (decl) = init; + goto finish_end; + } + if (TREE_CODE (init) == TREE_LIST) { /* If the parenthesized-initializer form was used (e.g., diff --git a/gcc/testsuite/g++.dg/template/const4.C b/gcc/testsuite/g++.dg/template/const4.C new file mode 100644 index 0000000..6552ec6e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/const4.C @@ -0,0 +1,9 @@ +// PR c++/48657 + +template struct A { typedef int T; }; + +template void f() +{ + const unsigned D = 4; + A::T t; +} diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6309648..cf4a40e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5750,7 +5750,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, const char *asmspec = NULL; int was_readonly = 0; bool var_definition_p = false; - int saved_processing_template_decl; tree auto_node; if (decl == error_mark_node) @@ -5772,7 +5771,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, /* Assume no cleanup is required. */ cleanup = NULL_TREE; - saved_processing_template_decl = processing_template_decl; /* If a name was specified, get the string. */ if (global_scope_p (current_binding_level)) @@ -5878,39 +5876,24 @@ 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 - && DECL_CLASS_SCOPE_P (decl) - /* We just set TREE_CONSTANT appropriately; see above. */ - && TREE_CONSTANT (decl) - && !type_dependent_p - /* FIXME non-value-dependent constant expression */ - && !value_dependent_init_p (init))) + if (init + && init_const_expr_p + && !type_dependent_p + && decl_maybe_constant_var_p (decl) + && !value_dependent_init_p (init)) { - if (init) - DECL_INITIAL (decl) = init; - if (TREE_CODE (decl) == VAR_DECL - && !DECL_PRETTY_FUNCTION_P (decl) - && !type_dependent_p) - maybe_deduce_size_from_array_init (decl, init); - goto finish_end; + 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) + maybe_deduce_size_from_array_init (decl, init); - if (TREE_CODE (init) == TREE_LIST) - { - /* If the parenthesized-initializer form was used (e.g., - "int A::i(X)"), then INIT will be a TREE_LIST of initializer - arguments. (There is generally only one.) We convert them - individually. */ - tree list = init; - for (; list; list = TREE_CHAIN (list)) - { - tree elt = TREE_VALUE (list); - TREE_VALUE (list) = fold_non_dependent_expr (elt); - } - } - else - init = fold_non_dependent_expr (init); - processing_template_decl = 0; + if (init) + DECL_INITIAL (decl) = init; + return; } /* Take care of TYPE_DECLs up front. */ @@ -5933,7 +5916,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), at_eof); - goto finish_end; + return; } /* A reference will be modified here, as it is initialized. */ @@ -6057,8 +6040,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, else if (TREE_CODE (type) == ARRAY_TYPE) layout_type (type); - if (!processing_template_decl - && TREE_STATIC (decl) + if (TREE_STATIC (decl) && !at_function_scope_p () && current_function_decl == NULL) /* So decl is a global variable or a static member of a @@ -6078,9 +6060,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, /* Let the middle end know about variables and functions -- but not static data members in uninstantiated class templates. */ - if (!saved_processing_template_decl - && (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL)) + if (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL) { if (TREE_CODE (decl) == VAR_DECL) { @@ -6167,9 +6148,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (cleanup) push_cleanup (decl, cleanup, false); - finish_end: - processing_template_decl = saved_processing_template_decl; - if (was_readonly) TREE_READONLY (decl) = 1; } diff --git a/gcc/testsuite/g++.dg/template/const4.C b/gcc/testsuite/g++.dg/template/const4.C new file mode 100644 index 0000000..6552ec6e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/const4.C @@ -0,0 +1,9 @@ +// PR c++/48657 + +template struct A { typedef int T; }; + +template void f() +{ + const unsigned D = 4; + A::T t; +}