PING: [RFC] PR c++/43206
Dodji Seketeli
dodji@redhat.com
Thu Mar 18 14:51:00 GMT 2010
On Thu, Mar 04, 2010 at 09:47:37PM +0100, Dodji Seketeli wrote:
> Hello,
>
> In the example of the patch below we fail to compare template type parms
> when we are still parsing template parameters. In that case, the
> DECL_CONTEXT of the TYPE_NAME of the template type parms is not set yet,
> because it's set later when the containing TEMPLATE_DECL is created in
> push_template_decl_real.
>
> A/ It would be convenient to say that if T1 and T2 are template type
> parms -- one of them being a typedef variant -- and if we could get the
> template parms T1 belongs to, but failed to get the template parms T2
> belongs to, (because we get NULL_TREE instead) then it would mean T1 and
> T2 are incompatible.
>
> B/ But that assumption would break other codes like:
> template<class T>
> struct S
> {
> typedef T TT;
> TT foo(); //#1
> };
>
> template<class T>
> T S<t>::foo(); //#2
>
> When we reach #2 start_decl -- by mean of maybe_push_decl -- must
> compare #1 and #2 and recognize that #2 is the same decl as #1, merge
> the two decls and only then create a TEMPLATE_DECL for #2. Thus the
> DECL_CONTEXT of the TYPE_NAME of T is empty for #2 during the type
> comparison of T (in #2) and TT that happens when comparing the decls #1
> and #2. The A/ assumption would thus make #2 be different from #1.
>
> So I temporarily set the DECL_CONTEXT of the TYPE_NAME of each template
> type parm to the list of parms it belongs to in end_template_parm_list.
> That removes problem B/.
> The DECL_CONTEXT would then be later set to the proper TEMPLATE_DECL in
> push_template_decl_real.
>
> I guess this allows me to make assumption A/, unless there are cases
> other than B for which A/ is not correct. Can you see other cases like
> that?
>
> FWIW, tested on x86_64-unknown-linux-gnu against trunk.
>
> Dodji
>
> commit eeec5b3c414d67e4290e9370710400f4a5024902
> Author: Dodji Seketeli <dodji@redhat.com>
> Date: Thu Mar 4 18:42:20 2010 +0100
>
> Fix candidate for PR c++/43206
>
> gcc/cp/ChangeLog:
> PR c++/43206
> * pt.c (end_template_parm_list): Temporarily set DECL_CONTEXT
> of the type decl of template type parm to the list of
> template parameters it belongs to.
> * typeck.c (get_template_parms_of_dependent_type): Try to get template
> parms's TREE_LIST from DECL_CONTEXT of template type parm when
> the containing DECL_TEMPLATE is not created.
> (incompatible_dependent_types_p): If we get empty parms from just one
> of the template type parms we are comparing then the template parms are
> incompatible.
>
> gcc/testsuite/ChangeLog:
> PR c++/43206
> * g++.dg/template/typedef30.C: New test case.
>
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index f5d3851..64e2b15 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -3549,6 +3549,17 @@ end_template_parm_list (tree parms)
> next = TREE_CHAIN (parm);
> TREE_VEC_ELT (saved_parmlist, nparms) = parm;
> TREE_CHAIN (parm) = NULL_TREE;
> + if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
> + /* Temporarily set the DECL_CONTEXT of the parm decl to the
> + list of template parms this type parm belongs to. This is useful
> + to be able to do proper type comparison between typedefs of
> + dependent types because in those cases we need to compare the
> + parms of the template the typedefs belong to.
> + See function incompatible_dependent_types_p.
> + In any case, later when the TEMPLATE_DECL these template parms
> + belong to is created push_template_decl_real fixes
> + this up and assigns this DECL_CONTEXT to that TEMPLATE_DECL. */
> + DECL_CONTEXT (TREE_VALUE (parm)) = current_template_parms;
> }
>
> --processing_template_parmlist;
> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> index b9ef78f..0fc8089 100644
> --- a/gcc/cp/typeck.c
> +++ b/gcc/cp/typeck.c
> @@ -1110,11 +1110,19 @@ get_template_parms_of_dependent_type (tree t)
> template info from T itself. */
> if ((tinfo = get_template_info (t)))
> ;
> + else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> + && DECL_CONTEXT (TYPE_NAME (t))
> + && TREE_CODE (DECL_CONTEXT (TYPE_NAME (t))) == TREE_LIST)
> + /* This means we have not yet created the DECL_TEMPLATE this
> + template type parm belongs to. In that case,
> + DECL_CONTEXT (TYPE_NAME (t)) contains the TREE_LIST of the
> + template parms -- see end_template_parm_list. Return it. */
> + return DECL_CONTEXT (TYPE_NAME (t));
> /* If T1 is a typedef or whatever has a template info associated
> to its context, get the template parameters from that context. */
> else if (typedef_variant_p (t)
> - && DECL_CONTEXT (TYPE_NAME (t))
> - && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
> + && DECL_CONTEXT (TYPE_NAME (t))
> + && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
> tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
> else if (TYPE_CONTEXT (t)
> && !NAMESPACE_SCOPE_P (t))
> @@ -1170,6 +1178,17 @@ incompatible_dependent_types_p (tree t1, tree t2)
> tparms1 = get_template_parms_of_dependent_type (t1);
> tparms2 = get_template_parms_of_dependent_type (t2);
>
> + /* If T2 is a template type parm and if we could not get the template
> + parms it belongs to, that means we have not finished parsing the
> + full set of template parameters of the template declaration it
> + belongs to yet. If we could get the template parms T1 belongs to,
> + that mostly means T1 and T2 belongs to templates that are
> + different and incompatible. */
> + if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
> + && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
> + && tparms1 != tparms2)
> + return true;
> +
> if (tparms1 == NULL_TREE
> || tparms2 == NULL_TREE
> || tparms1 == tparms2)
> diff --git a/gcc/testsuite/g++.dg/template/typedef30.C b/gcc/testsuite/g++.dg/template/typedef30.C
> new file mode 100644
> index 0000000..2f9362a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/typedef30.C
> @@ -0,0 +1,20 @@
> +// Origin: PR c++/43206
> +// { dg-do compile }
> +
> +template<class A> struct NumericTraits{ typedef A TInputImage;};
> +template<class B> class CovariantVector{};
> +template<class C> struct Image{ typedef C PixelType;};
> +template<class H, class E, class D>
> +class F {
> + typedef H G;
> + typedef
> + typename NumericTraits<typename G::PixelType>::RealType
> + InputRealType;
> +};
> +
> +template<typename TInputImage,
> + typename TOutputImage=Image<CovariantVector<typename NumericTraits<typename TInputImage::PixelType>::TInputImage> > >
> +class XXX{};
> +
> +XXX<Image<float> > x;
> +
Dodji
More information about the Gcc-patches
mailing list