From patchwork Thu Dec 5 22:50:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 297445 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)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 93CD52C00A1 for ; Fri, 6 Dec 2013 09:50:45 +1100 (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:content-type; q= dns; s=default; b=QXIH3PHYe4EK1blSaIDOrfnvxOqvkm/bBoU2mCbh0dyARZ tzDIGbPJ3r7jFxZkupuEgetWAUSDmSCD0tQ3grTlmTEe7x6NJJx01QYJNhZ7i7nb 2/MD2KojMxKVhVEcq99ydoRCxhGzQLl1OCLaU7cyAdmzerg6xrsbcS1GPl9qc= 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:content-type; s= default; bh=wB3+tzSoXtpSl7yISCWzJHpsEVk=; b=CITDv+Q/VW4wi1G1ISoX bT3wH4/J9sjdAtdofHUJ4h9LpKXwHosZyjXx3vMwKqHpfy4uloJKZAMoHx+q7401 gbQ6PaY9yhG2fEvZEq2FU6JqzK7x/EPGYVvt7tdBD8FHscKUIu8bKqj7hZRNWYT0 IwWxmuhh/DRTfvVCl4G+25c= Received: (qmail 32741 invoked by alias); 5 Dec 2013 22:50:38 -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 32729 invoked by uid 89); 5 Dec 2013 22:50:38 -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, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from Unknown (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 05 Dec 2013 22:50:37 +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 rB5MoTm9018771 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 5 Dec 2013 17:50:29 -0500 Received: from [10.10.116.18] ([10.10.116.18]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id rB5MoSBj003443 for ; Thu, 5 Dec 2013 17:50:29 -0500 Message-ID: <52A10334.4060103@redhat.com> Date: Thu, 05 Dec 2013 17:50:28 -0500 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.1.0 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/59044 (partial specialization of member class template) If a non-type template parameter of a member class template depends on template parameters from the enclosing class template, we need to use the partially instantiated version of the member template in deduction. Tested x86_64-pc-linux-gnu, applying to trunk and 4.8. commit d77a6d36bd910be2e1b8a9ccece95fac791d84e1 Author: Jason Merrill Date: Thu Dec 5 14:04:19 2013 -0500 PR c++/59044 PR c++/59052 * pt.c (most_specialized_class): Use the partially instantiated template for deduction. Drop the TMPL parameter. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 25d940c..01b2d44 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -176,7 +176,7 @@ static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree); static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree); static tree tsubst_template_parms (tree, tree, tsubst_flags_t); static void regenerate_decl_from_template (tree, tree); -static tree most_specialized_class (tree, tree, tsubst_flags_t); +static tree most_specialized_class (tree, tsubst_flags_t); static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int); static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree); static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); @@ -4305,7 +4305,7 @@ process_partial_specialization (tree decl) if (COMPLETE_TYPE_P (inst_type) && CLASSTYPE_IMPLICIT_INSTANTIATION (inst_type)) { - tree spec = most_specialized_class (inst_type, maintmpl, tf_none); + tree spec = most_specialized_class (inst_type, tf_none); if (spec && TREE_TYPE (spec) == type) permerror (input_location, "partial specialization of %qT after instantiation " @@ -8716,7 +8716,7 @@ instantiate_class_template_1 (tree type) /* Determine what specialization of the original template to instantiate. */ - t = most_specialized_class (type, templ, tf_warning_or_error); + t = most_specialized_class (type, tf_warning_or_error); if (t == error_mark_node) { TYPE_BEING_DEFINED (type) = 1; @@ -18242,7 +18242,7 @@ more_specialized_fn (tree pat1, tree pat2, int len) return -1; } -/* Determine which of two partial specializations of MAIN_TMPL is more +/* Determine which of two partial specializations of TMPL is more specialized. PAT1 is a TREE_LIST whose TREE_TYPE is the _TYPE node corresponding @@ -18258,7 +18258,7 @@ more_specialized_fn (tree pat1, tree pat2, int len) two templates is more specialized. */ static int -more_specialized_class (tree main_tmpl, tree pat1, tree pat2) +more_specialized_class (tree tmpl, tree pat1, tree pat2) { tree targs; tree tmpl1, tmpl2; @@ -18273,7 +18273,7 @@ more_specialized_class (tree main_tmpl, tree pat1, tree pat2) types in the arguments, and we need our dependency check functions to behave correctly. */ ++processing_template_decl; - targs = get_class_bindings (main_tmpl, TREE_VALUE (pat1), + targs = get_class_bindings (tmpl, TREE_VALUE (pat1), CLASSTYPE_TI_ARGS (tmpl1), CLASSTYPE_TI_ARGS (tmpl2)); if (targs) @@ -18282,7 +18282,7 @@ more_specialized_class (tree main_tmpl, tree pat1, tree pat2) any_deductions = true; } - targs = get_class_bindings (main_tmpl, TREE_VALUE (pat2), + targs = get_class_bindings (tmpl, TREE_VALUE (pat2), CLASSTYPE_TI_ARGS (tmpl2), CLASSTYPE_TI_ARGS (tmpl1)); if (targs) @@ -18363,7 +18363,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype) } /* Return the innermost template arguments that, when applied to a partial - specialization of MAIN_TMPL whose innermost template parameters are + specialization of TMPL whose innermost template parameters are TPARMS, and whose specialization arguments are SPEC_ARGS, yield the ARGS. @@ -18378,7 +18378,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype) is bound to `double'. */ static tree -get_class_bindings (tree main_tmpl, tree tparms, tree spec_args, tree args) +get_class_bindings (tree tmpl, tree tparms, tree spec_args, tree args) { int i, ntparms = TREE_VEC_LENGTH (tparms); tree deduced_args; @@ -18418,8 +18418,8 @@ get_class_bindings (tree main_tmpl, tree tparms, tree spec_args, tree args) `T' is `A' but unify () does not check whether `typename T::X' is `int'. */ spec_args = tsubst (spec_args, deduced_args, tf_none, NULL_TREE); - spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (main_tmpl), - spec_args, main_tmpl, + spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), + spec_args, tmpl, tf_none, false, false); if (spec_args == error_mark_node /* We only need to check the innermost arguments; the other @@ -18567,30 +18567,30 @@ most_general_template (tree decl) } /* Return the most specialized of the class template partial - specializations of TMPL which can produce TYPE, a specialization of - TMPL. The value returned is actually a TREE_LIST; the TREE_TYPE is + specializations which can produce TYPE, a specialization of some class + template. The value returned is actually a TREE_LIST; the TREE_TYPE is a _TYPE node corresponding to the partial specialization, while the TREE_PURPOSE is the set of template arguments that must be substituted into the TREE_TYPE in order to generate TYPE. If the choice of partial specialization is ambiguous, a diagnostic is issued, and the error_mark_node is returned. If there are no - partial specializations of TMPL matching TYPE, then NULL_TREE is - returned. */ + partial specializations matching TYPE, then NULL_TREE is + returned, indicating that the primary template should be used. */ static tree -most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) +most_specialized_class (tree type, tsubst_flags_t complain) { tree list = NULL_TREE; tree t; tree champ; int fate; bool ambiguous_p; - tree args; tree outer_args = NULL_TREE; - tmpl = most_general_template (tmpl); - args = CLASSTYPE_TI_ARGS (type); + tree tmpl = CLASSTYPE_TI_TEMPLATE (type); + tree main_tmpl = most_general_template (tmpl); + tree args = CLASSTYPE_TI_ARGS (type); /* For determining which partial specialization to use, only the innermost args are interesting. */ @@ -18600,7 +18600,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) args = INNERMOST_TEMPLATE_ARGS (args); } - for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t)) + for (t = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); t; t = TREE_CHAIN (t)) { tree partial_spec_args; tree spec_args; @@ -18625,8 +18625,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) partial_spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), - add_to_template_args (outer_args, - partial_spec_args), + partial_spec_args, tmpl, tf_none, /*require_all_args=*/true, /*use_default_args=*/true); diff --git a/gcc/testsuite/g++.dg/template/partial14.C b/gcc/testsuite/g++.dg/template/partial14.C new file mode 100644 index 0000000..3870164 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/partial14.C @@ -0,0 +1,16 @@ +// PR c++/59044 + +template +class C { +private: + template + struct Implementation {}; +public: + typedef typename Implementation<0, 0>::Typedef Type; +}; + +template +template +struct C::Implementation<0, b> { typedef void Typedef; }; + +template class C;