From patchwork Tue Sep 28 11:25:57 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 65957 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 55A22B70A8 for ; Tue, 28 Sep 2010 21:26:13 +1000 (EST) Received: (qmail 18021 invoked by alias); 28 Sep 2010 11:26:09 -0000 Received: (qmail 18009 invoked by uid 22791); 28 Sep 2010 11:26:07 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, TW_RG, TW_SB X-Spam-Check-By: sourceware.org Received: from seketeli.net (HELO ms.seketeli.net) (91.121.166.71) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 28 Sep 2010 11:26:01 +0000 Received: from adjoa.torimasen.com (torimasen.com [82.237.12.13]) by ms.seketeli.net (Postfix) with ESMTP id 347C31608038; Tue, 28 Sep 2010 13:23:34 +0200 (CEST) Received: from adjoa.seketeli.org (localhost.localdomain [127.0.0.1]) by adjoa.torimasen.com (Postfix) with ESMTP id DE85B8E60A6; Tue, 28 Sep 2010 13:25:57 +0200 (CEST) From: Dodji Seketeli To: Jason Merrill Cc: "H.J. Lu" , Paolo Carlini , GCC Patches Subject: Re: Require canonical type comparison for typedefs again. References: <4C630F87.9060303@redhat.com> <4C640257.4080804@redhat.com> <4C9673B7.5010505@oracle.com> <4C97C9E5.2090907@redhat.com> <4C9E863C.30208@redhat.com> X-URL: http://www.seketeli.net/~dodji Date: Tue, 28 Sep 2010 13:25:57 +0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes 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 Jason Merrill writes: [...] >>>> + if (total_num_parms == 0) >>>> + return NULL_TREE; >>> >>> Since you're already treating parms from a list of unknown length as >>> distinct from parms from a list of known length, we can give them a >>> canonical type, too. >> >> Doing that doesn't seem to work. The problem is not with the comparison >> of type template parms but rather with the comparison of dependent types >> created during the template parms parsing. >> >> If type template parms don't require structural comparison then a type A >> (created during template parms parsing) dependent on those parms will >> have a canonical type. > > Yep. > >> The fixup then creates a type A' that is >> structurally equivalent to A, but has a different canonical type. > > It shouldn't be structurally equivalent, since A's template parms come > from a list of non-0 length, which is not true of A'. > I must be missing something. In structural_comptype, in the RECORD_TYPE case, comp_template_args is called and I think this eventually compares the template parms of A and A' using their canonical types, even though we are calling from structural_comptype and are supposed to do structural comparison. Hence A and A' will is considered structurally equivalent. No? >> * Template parm level reduction. >> >> When at least one of the parms is itself a template [like in >> testsuite/g++.old-deja/g++.pt/nttp1.C] then at some point we end up in >> tsubst (at least) with an argument set that has a depth that is less >> than the depth of the parm of the template template parm we are >> susbtituting into. > > Rather, the problem comes when we don't have any argument at all; in > that case we reduce the level. > >> My understanding is that the tsubsting code then thinks that we are >> doing the substitution for the purpose of instantiation and then reduces >> the level of the resulting parms. > > Partial instantiation, yes. > > I would expect that when we get to this point we've already done the > fixup for these parms, so that they don't need to be substituted > directly; we only need to fixup the type of any non-type parms (and so > on recursively for template template parms). That ought to avoid this > problem. Just to be sure I understand; do you mean I should write a function that recursively does type substitution for non-type parms (only) of template template parms and use that in the fixup? Or does such a function exists already? [...] > >> Incidentally I noticed that the tf_no_class_instantiation is not used by >> any client code anymore. Would you accept a patchlet to remove it? > > Yep. > >> During unification of C<5> with X<5> the argument 5 of X is converted >> into the type of the parameter of C, i.e 5 is converted into typename >> metafun::type. convert_template_argument then tries to substitute >> into typename metafun::type. This should just create another >> equivalent typename becase metafun is dependent and thus non >> complete. But when tsubst calls make_typename_type, the later fails to >> detect that metafun is dependent [because processing_template_decl is >> 0] and goes crazy. > > Why don't we have an argument for T by this point? Good question. I seems T's argument is "lost" somehow even in current trunk without my patch. I think what happens is that unify (in the BOUND_TEMPLATE_TEMPLATE_PARM case) calls coerce_template_parms with an argvec that is just the innermost template arguments of C<5>, which is {5}. I think it should call it with the full set of template arguments including the arguments deduced so far i.e, {{5}, {5}}. The depth of that full set would be 2. The first level of arguments is the argument for T (the first {5}), and the second set (the second {5}) would be to unified with "metafun<5>::type" to deduce "int". This hunk -- similar to what is done in lookup_template_class in the "if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))" branch -- seems to fix the issue: ~=~ ~=~ I have removed the use of use_template_parms in make_typename_type from make_typename_type thus. Does this make more sense? Thanks. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e060cc7..bf13978 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -14914,6 +14914,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) { tree parmvec = TYPE_TI_ARGS (parm); tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg)); + tree full_argvec = add_to_template_args (targs, argvec); tree parm_parms = DECL_INNERMOST_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm)); @@ -14948,7 +14949,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) the global operator+ will be used; if they are not, the Lvalue_proxy will be converted to float. */ if (coerce_template_parms (parm_parms, - argvec, + full_argvec, TYPE_TI_TEMPLATE (parm), tf_none, /*require_all_args=*/true,