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