From patchwork Fri Jul 16 21:02:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: C++ PATCH for c++/32505 (missed error on partial specialization after instantiation) Date: Fri, 16 Jul 2010 11:02:27 -0000 From: Jason Merrill X-Patchwork-Id: 59127 Message-Id: <4C40C8E3.2090505@redhat.com> To: gcc-patches List While looking at another issue, I noticed that we weren't diagnosing this. The standard says that no diagnostic is required, but it seems like it's something that users would really want us to catch. So now we do. Tested x86_64-pc-linux-gnu, applied to trunk. commit 846bfa71c1aeb0758caf3841637a2450baec8715 Author: Jason Merrill Date: Fri Jul 16 16:14:33 2010 -0400 PR c++/32505 * pt.c (process_partial_specialization): Diagnose partial specialization after instantiation. (most_specialized_class): Add complain parm. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ef6e8e9..3259043 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -158,7 +158,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); +static tree most_specialized_class (tree, tree, tsubst_flags_t); static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int); static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree); static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); @@ -3831,6 +3831,7 @@ process_partial_specialization (tree decl) tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs); tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl); tree inner_parms; + tree inst; int nargs = TREE_VEC_LENGTH (inner_args); int ntparms; int i; @@ -4045,6 +4046,22 @@ process_partial_specialization (tree decl) = tree_cons (specargs, inner_parms, DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)); TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type; + + for (inst = DECL_TEMPLATE_INSTANTIATIONS (maintmpl); inst; + inst = TREE_CHAIN (inst)) + { + tree inst_type = TREE_VALUE (inst); + if (COMPLETE_TYPE_P (inst_type) + && CLASSTYPE_IMPLICIT_INSTANTIATION (inst_type)) + { + tree spec = most_specialized_class (inst_type, maintmpl, tf_none); + if (spec && TREE_TYPE (spec) == type) + permerror (input_location, + "partial specialization of %qT after instantiation " + "of %qT", type, inst_type); + } + } + return decl; } @@ -7749,7 +7766,7 @@ instantiate_class_template (tree type) /* Determine what specialization of the original template to instantiate. */ - t = most_specialized_class (type, templ); + t = most_specialized_class (type, templ, tf_warning_or_error); if (t == error_mark_node) { TYPE_BEING_DEFINED (type) = 1; @@ -15974,7 +15991,7 @@ most_general_template (tree decl) returned. */ static tree -most_specialized_class (tree type, tree tmpl) +most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) { tree list = NULL_TREE; tree t; @@ -16094,6 +16111,8 @@ most_specialized_class (tree type, tree tmpl) { const char *str; char *spaces = NULL; + if (!(complain & tf_error)) + return error_mark_node; error ("ambiguous class template instantiation for %q#T", type); str = TREE_CHAIN (list) ? _("candidates are:") : _("candidate is:"); for (t = list; t; t = TREE_CHAIN (t)) diff --git a/gcc/testsuite/g++.dg/template/partial8.C b/gcc/testsuite/g++.dg/template/partial8.C new file mode 100644 index 0000000..4db7e18 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/partial8.C @@ -0,0 +1,4 @@ +// PR c++/32505 +template struct A { }; +A a; +template struct A { }; // { dg-error "A" }