On 03/08/2012 08:21 AM, Dodji Seketeli wrote:
So I needed to say somehow that the P in the pack expansion
(in the pattern) is actually a Pr "in spirit".

Ah, I see.

+                                    /*we will fixup the siblings for

Space and capital W.

+get_root_index_same_level (tree index)
+{
+  tree i = index;
+
+  if (TREE_CODE (TEMPLATE_PARM_DECL (i)) == CONST_DECL)
+    {
+      if (TEMPLATE_PARM_ORIG_LEVEL (i) == TEMPLATE_PARM_LEVEL (index))
+       i = TEMPLATE_PARM_ORIG_INDEX (i);

If the levels are the same, shouldn't the ORIG_INDEX already be the same as index?

+  else
+    {
+      if (template_type_parameter_type_p (TREE_TYPE (i))
+         && TREE_CODE (TEMPLATE_PARM_DECL (i)) != CONST_DECL
+         && TYPE_CANONICAL (TREE_TYPE (i)) != NULL_TREE)

You already checked the TREE_CODE of TEMPLATE_PARM_DECL in the outer if. And if it's not a CONST_DECL, it must be either a type parameter or template parameter. So I think you only need the last test here.

+get_template_parameter_level_and_index (tree parameter, int *level, int *index)
+{
+  int l = 0, i = -1;
+  tree parm;
+
+  if (TREE_CODE (parameter) == TYPE_DECL
+      || TREE_CODE (parameter) == TEMPLATE_DECL)
+    parm = TREE_TYPE (parameter);
+  else if (TREE_CODE (parameter) == PARM_DECL)
+    parm = DECL_INITIAL (parameter);
+  else
+    parm = parameter;
+
+  template_parm_level_and_index (parm, &l, &i);

Why not extend template_parm_level_and_index to handle these cases as well?

+    properly appends the descender of INDEX to that

descendant

+      if (*where == NULL_TREE)
+       TREE_VEC_ELT (TEMPLATE_PARM_DESCENDANTS (index),
+                     TEMPLATE_PARM_LEVEL (descendant) - 1) = descendant;

Why not "*where = descendant"?

+             && (DECL_SOURCE_LOCATION (TEMPLATE_PARM_DECL (result))
+                 != DECL_SOURCE_LOCATION (TEMPLATE_PARM_DECL (orig_index))))
+           {
+             /*  We have gotten an equivalent index, that was reduced
+                 from index from ORIG_INDEX, but which (location of)
+                 DECL is different.  This can lead to having error
+                 messages pointing to the wrong location, so let's
+                 build an equivalent TEMPLATE_PARM_INDEX with a DECL
+                 pointing to the same location as ORIG_INDEX for
+                 RESULT.  */

How can this happen?  Hmm, I guess it's because of

+       i = TEMPLATE_TYPE_PARM_INDEX (TYPE_CANONICAL (TREE_TYPE (i)));

Why do we want to go to the canonical type parameter (which has no name) rather than just TYPE_MAIN_VARIANT?

I think it makes more sense to reduce the index we have, rather than reduce the canonical index and then adjust the result to match the index we have.

+  /* Template parms ought to be fixed-up from left to right.  */
+  parms = nreverse (parms);

I'm a bit nervous about something called by fixup getting confused by this change to the template parms before we change it back.

+/*  Transform a template parameter into an argument, suitable to be
+    passed to tsubst as an element of its ARGS parameter.  */
+
+static tree
+template_parms_to_args (tree parms)

The comment seems to be talking about a single parm.

+      /* This can happen for template parms of a template template
+        parameter, e.g:
+
+        template<template<class T, class U> class TT> struct S;
+
+        Consider the level of the parms of TT; T and U both have
+        level 2; TT has no template parm of level 1. So in this case
+        the first element of full_template_args is NULL_TREE. If we
+        leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+        of 2. This will make tsubst wrongly consider that T and U
+        have level 1. Instead, let's create a dummy vector as the
+        first element of full_template_args so that TMPL_ARG_DEPTH
+        returns the correct depth for args.  */

Hmm, it seems odd that the parms wouldn't have level 1. I wonder if changing that would also avoid needing to use structural equality for template template parameters.

   FIXME: This function does an approximation, as it only checks that
   the levels of PARM_PACK/EXPANSION and ARG_PACK do match.  For it to
   be precise, I think the TEMPLATE_PARM_INDEX of PARM_PACK should
   track its pre-fixup type, so that ARG_PACK could be compared with
   that type instead.  But that would increase the size of the
   template_parm_index_s struct, as I don't see where else I could
   store the pre-fixup type.  */

Doesn't ...ORIG_INDEX work for this? Indeed, I'd think you could change arg_from_parm_pack_p to compare ORIG_INDEX and then it would handle both cases.

+      if (tinfo && TREE_CODE (TI_TEMPLATE (tinfo)) == TEMPLATE_DECL)
+       {
+         ++processing_template_decl;
+         /* prepare possible partial instantiation of member
+            template by fixing-up template parms which level are
+            going to be reduced by the partial instantiation.  */
+         tsubst_template_parms (DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo)),
+                                args, tf_none);
+         --processing_template_decl;
+       }

This doesn't seem necessary for member functon templates, since we fix up the parms first thing in tsubst_decl. Is it necessary for member class templates? Can we handle it at a lower level there, too?

     case UNBOUND_CLASS_TEMPLATE:
       {
+       /* If T is a member template being partially instantiated,
+          fixup its template parmeters that are to be level-reduced,
+          upfront.  */
+       tree parm_list =
+         tsubst_template_parms (DECL_TEMPLATE_PARMS (TYPE_NAME (t)),
+                                args, complain);

This comment could be clearer; an UNBOUND_CLASS_TEMPLATE isn't a member template, though it will eventually be replaced with one.

Jason

Reply via email to