From 5cc2edcde433b1edff1699b372d5e70cc0690c88 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 5 Dec 2013 17:46:36 -0500 Subject: [PATCH] re PR c++/59044 (Internal compiler error triggers when accessing a typedef in a specialized member class) PR c++/59044 PR c++/59052 * pt.c (most_specialized_class): Use the partially instantiated template for deduction. Drop the TMPL parameter. From-SVN: r205720 --- gcc/cp/ChangeLog | 7 +++++ gcc/cp/pt.c | 43 +++++++++++++++---------------- gcc/testsuite/g++.dg/template/partial14.C | 16 ++++++++++++ 3 files changed, 44 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/partial14.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2d5617a..16b6aa0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2013-12-05 Jason Merrill + + PR c++/59044 + PR c++/59052 + * pt.c (most_specialized_class): Use the partially instantiated + template for deduction. Drop the TMPL parameter. + 2013-12-05 Paolo Carlini * decl.c (duplicate_decls): Replace pairs of errors and permerrors 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..3870164f --- /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; -- 2.7.4