From patchwork Fri Jul 16 21:02:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 59127 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 493B8B6EF0 for ; Sat, 17 Jul 2010 07:02:38 +1000 (EST) Received: (qmail 9797 invoked by alias); 16 Jul 2010 21:02:36 -0000 Received: (qmail 9651 invoked by uid 22791); 16 Jul 2010 21:02:35 -0000 X-SWARE-Spam-Status: No, hits=-6.0 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; Fri, 16 Jul 2010 21:02:29 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o6GL2SNt027047 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 16 Jul 2010 17:02:28 -0400 Received: from [IPv6:::1] (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6GL2R2r007259 for ; Fri, 16 Jul 2010 17:02:28 -0400 Message-ID: <4C40C8E3.2090505@redhat.com> Date: Fri, 16 Jul 2010 17:02:27 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.10) Gecko/20100712 Lightning/1.0b1 Shredder/3.0.7pre MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/32505 (missed error on partial specialization after instantiation) 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 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" }