Hi,

On 05/02/2012 01:46 AM, Jason Merrill wrote:
On 05/01/2012 07:39 PM, Paolo Carlini wrote:
I'm sorry, when a few days ago I noticed that we weren't tsubsting at all I thought the fix would be quite straightforward for me to handle because very local I didn't expect we would go ahead and resolve the FIXME about instantiation-dependent

No worries, thanks for sticking with it.

Maybe we want to gcc_assert ((check_types && !fn) || !check_types) at
the beginning of walk_template_parms. I don't know.

!check_types || !fn, sounds good.
Indeed ;)

+  if (pfd->check_types && !TYPE_P (t) && TREE_TYPE (t) == NULL_TREE)
+    return error_mark_node;

Let's add a comment like: if the type is null, this is a type-dependent expression, and if we're checking types, we would find the relevant template parameters. And fn must be null, so we can just return.
Ok. I'm attaching below the "state of the art".

I think we need to handle FIELD_DECL, too.
Are there hopes that handling FIELD_DECL like FUNCTION_DECL and VAR_DECL (besides the DECL_LANG_SPECIFIC check) would work? Ie;

    case FIELD_DECL:
      if (DECL_TEMPLATE_INFO (t)
&& walk_template_parms (DECL_TI_ARGS (t), fn, data,
                                  pfd->visited, pfd->check_types,
                                  pfd->include_nondeduced_p))
        return error_mark_node;

Unfortunately I don't see anything explicit about FIELD_DECL in the various dependent_p things, no hints.

Thanks,
Paolo.




Index: cp/pt.c
===================================================================
--- cp/pt.c     (revision 187012)
+++ cp/pt.c     (working copy)
@@ -145,8 +145,8 @@ static tree convert_nontype_argument_function (tre
 static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
 static tree convert_template_argument (tree, tree, tree,
                                       tsubst_flags_t, int, tree);
-static int for_each_template_parm (tree, tree_fn_t, void*,
-                                  struct pointer_set_t*, bool);
+static int walk_template_parms (tree, tree_fn_t, void*,
+                               struct pointer_set_t*, bool, bool);
 static tree expand_template_argument_pack (tree);
 static tree build_template_parm_index (int, int, int, int, tree, tree);
 static bool inline_needs_template_parms (tree);
@@ -185,7 +185,7 @@ static int coerce_template_template_parms (tree, t
 static bool template_template_parm_bindings_ok_p (tree, tree);
 static int template_args_equal (tree, tree);
 static void tsubst_default_arguments (tree);
-static tree for_each_template_parm_r (tree *, int *, void *);
+static tree walk_template_parms_r (tree *, int *, void *);
 static tree copy_default_args_to_explicit_spec_1 (tree, tree);
 static void copy_default_args_to_explicit_spec (tree);
 static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
@@ -4276,8 +4276,8 @@ mark_template_parm (tree t, void* data)
       tpd->arg_uses_template_parms[tpd->current_arg] = 1;
     }
 
-  /* Return zero so that for_each_template_parm will continue the
-     traversal of the tree; we want to mark *every* template parm.  */
+  /* Return zero so that walk_template_parms will continue the traversal
+     of the tree; we want to mark *every* template parm.  */
   return 0;
 }
 
@@ -4344,11 +4344,12 @@ process_partial_specialization (tree decl)
   for (i = 0; i < nargs; ++i)
     {
       tpd.current_arg = i;
-      for_each_template_parm (TREE_VEC_ELT (inner_args, i),
-                             &mark_template_parm,
-                             &tpd,
-                             NULL,
-                             /*include_nondeduced_p=*/false);
+      walk_template_parms (TREE_VEC_ELT (inner_args, i),
+                          &mark_template_parm,
+                          &tpd,
+                          NULL,
+                          /*check_types=*/false,
+                          /*include_nondeduced_p=*/false);
     }
   for (i = 0; i < ntparms; ++i)
     if (tpd.parms[i] == 0)
@@ -4481,11 +4482,12 @@ process_partial_specialization (tree decl)
                   tpd2.current_arg = i;
                   tpd2.arg_uses_template_parms[i] = 0;
                   memset (tpd2.parms, 0, sizeof (int) * nargs);
-                  for_each_template_parm (type,
-                                          &mark_template_parm,
-                                          &tpd2,
-                                          NULL,
-                                         /*include_nondeduced_p=*/false);
+                  walk_template_parms (type,
+                                      &mark_template_parm,
+                                      &tpd2,
+                                      NULL,
+                                      /*check_types=*/false,
+                                      /*include_nondeduced_p=*/false);
 
                   if (tpd2.arg_uses_template_parms [i])
                     {
@@ -4755,7 +4757,7 @@ check_default_tmpl_args (tree decl, tree parms, in
 }
 
 /* Worker for push_template_decl_real, called via
-   for_each_template_parm.  DATA is really an int, indicating the
+   walk_template_parms.  DATA is really an int, indicating the
    level of the parameters we are interested in.  If T is a template
    parameter of that level, return nonzero.  */
 
@@ -7750,26 +7752,34 @@ struct pair_fn_data
 {
   tree_fn_t fn;
   void *data;
+  bool check_types;
   /* True when we should also visit template parameters that occur in
      non-deduced contexts.  */
   bool include_nondeduced_p;
   struct pointer_set_t *visited;
 };
 
-/* Called from for_each_template_parm via walk_tree.  */
+/* Called from walk_template_parms via walk_tree.  */
 
 static tree
-for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
+walk_template_parms_r (tree *tp, int *walk_subtrees, void *d)
 {
   tree t = *tp;
   struct pair_fn_data *pfd = (struct pair_fn_data *) d;
   tree_fn_t fn = pfd->fn;
   void *data = pfd->data;
 
+  /* If the type is null, this is a type-dependent expression, and if
+     we're checking types, we would find the relevant template parameters.
+     And fn must be null, so we can just return.  */ 
+  if (pfd->check_types && !TYPE_P (t) && TREE_TYPE (t) == NULL_TREE)
+    return error_mark_node;
+
   if (TYPE_P (t)
       && (pfd->include_nondeduced_p || TREE_CODE (t) != TYPENAME_TYPE)
-      && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited,
-                                pfd->include_nondeduced_p))
+      && walk_template_parms (TYPE_CONTEXT (t), fn, data,
+                             pfd->visited, pfd->check_types,
+                             pfd->include_nondeduced_p))
     return error_mark_node;
 
   switch (TREE_CODE (t))
@@ -7783,34 +7793,39 @@ static tree
     case ENUMERAL_TYPE:
       if (!TYPE_TEMPLATE_INFO (t))
        *walk_subtrees = 0;
-      else if (for_each_template_parm (TI_ARGS (TYPE_TEMPLATE_INFO (t)),
-                                      fn, data, pfd->visited, 
-                                      pfd->include_nondeduced_p))
+      else if (walk_template_parms (TI_ARGS (TYPE_TEMPLATE_INFO (t)),
+                                   fn, data, pfd->visited,
+                                   pfd->check_types,
+                                   pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
     case INTEGER_TYPE:
-      if (for_each_template_parm (TYPE_MIN_VALUE (t),
-                                 fn, data, pfd->visited, 
-                                 pfd->include_nondeduced_p)
-         || for_each_template_parm (TYPE_MAX_VALUE (t),
-                                    fn, data, pfd->visited,
-                                    pfd->include_nondeduced_p))
+      if (walk_template_parms (TYPE_MIN_VALUE (t),
+                              fn, data, pfd->visited,
+                              pfd->check_types,
+                              pfd->include_nondeduced_p)
+         || walk_template_parms (TYPE_MAX_VALUE (t),
+                                 fn, data, pfd->visited,
+                                 pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
     case METHOD_TYPE:
       /* Since we're not going to walk subtrees, we have to do this
         explicitly here.  */
-      if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data,
-                                 pfd->visited, pfd->include_nondeduced_p))
+      if (walk_template_parms (TYPE_METHOD_BASETYPE (t), fn, data,
+                              pfd->visited, pfd->check_types,
+                              pfd->include_nondeduced_p))
        return error_mark_node;
       /* Fall through.  */
 
     case FUNCTION_TYPE:
       /* Check the return type.  */
-      if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited,
-                                 pfd->include_nondeduced_p))
+      if (walk_template_parms (TREE_TYPE (t), fn, data,
+                              pfd->visited, pfd->check_types,
+                              pfd->include_nondeduced_p))
        return error_mark_node;
 
       /* Check the parameter types.  Since default arguments are not
@@ -7823,8 +7838,9 @@ static tree
        tree parm;
 
        for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
-         if (for_each_template_parm (TREE_VALUE (parm), fn, data,
-                                     pfd->visited, pfd->include_nondeduced_p))
+         if (walk_template_parms (TREE_VALUE (parm), fn, data,
+                                  pfd->visited, pfd->check_types,
+                                  pfd->include_nondeduced_p))
            return error_mark_node;
 
        /* Since we've already handled the TYPE_ARG_TYPES, we don't
@@ -7836,37 +7852,46 @@ static tree
     case TYPEOF_TYPE:
     case UNDERLYING_TYPE:
       if (pfd->include_nondeduced_p
-         && for_each_template_parm (TYPE_FIELDS (t), fn, data,
-                                    pfd->visited, 
-                                    pfd->include_nondeduced_p))
+         && walk_template_parms (TYPE_FIELDS (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
     case FUNCTION_DECL:
     case VAR_DECL:
       if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
-         && for_each_template_parm (DECL_TI_ARGS (t), fn, data,
-                                    pfd->visited, pfd->include_nondeduced_p))
+         && walk_template_parms (DECL_TI_ARGS (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       /* Fall through.  */
 
     case PARM_DECL:
     case CONST_DECL:
       if (TREE_CODE (t) == CONST_DECL && DECL_TEMPLATE_PARM_P (t)
-         && for_each_template_parm (DECL_INITIAL (t), fn, data,
-                                    pfd->visited, pfd->include_nondeduced_p))
+         && walk_template_parms (DECL_INITIAL (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       if (DECL_CONTEXT (t)
          && pfd->include_nondeduced_p
-         && for_each_template_parm (DECL_CONTEXT (t), fn, data,
-                                    pfd->visited, pfd->include_nondeduced_p))
+         && walk_template_parms (DECL_CONTEXT (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
+      if (pfd->check_types && TREE_TYPE (t)
+         && walk_template_parms (TREE_TYPE(t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
+       return error_mark_node;
       break;
 
     case BOUND_TEMPLATE_TEMPLATE_PARM:
       /* Record template parameters such as `T' inside `TT<T>'.  */
-      if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited,
-                                 pfd->include_nondeduced_p))
+      if (walk_template_parms (TYPE_TI_ARGS (t), fn, data,
+                              pfd->visited, pfd->check_types,
+                              pfd->include_nondeduced_p))
        return error_mark_node;
       /* Fall through.  */
 
@@ -7882,8 +7907,9 @@ static tree
     case TEMPLATE_DECL:
       /* A template template parameter is encountered.  */
       if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
-         && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited,
-                                    pfd->include_nondeduced_p))
+         && walk_template_parms (TREE_TYPE (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
 
       /* Already substituted template template parameter */
@@ -7892,44 +7918,27 @@ static tree
 
     case TYPENAME_TYPE:
       if (!fn
-         || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn,
-                                    data, pfd->visited, 
-                                    pfd->include_nondeduced_p))
+         || walk_template_parms (TYPENAME_TYPE_FULLNAME (t), fn,
+                                 data, pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
     case CONSTRUCTOR:
       if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))
          && pfd->include_nondeduced_p
-         && for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
-                                    (TREE_TYPE (t)), fn, data,
-                                    pfd->visited, pfd->include_nondeduced_p))
+         && walk_template_parms (TYPE_PTRMEMFUNC_FN_TYPE
+                                 (TREE_TYPE (t)), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
-      break;
-
-    case INDIRECT_REF:
-    case COMPONENT_REF:
-      /* If there's no type, then this thing must be some expression
-        involving template parameters.  */
-      if (!fn && !TREE_TYPE (t))
+      else if (pfd->check_types && TREE_TYPE (t)
+              && walk_template_parms (TREE_TYPE (t), fn, data,
+                                      pfd->visited, pfd->check_types,
+                                      pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
-    case MODOP_EXPR:
-    case CAST_EXPR:
-    case IMPLICIT_CONV_EXPR:
-    case REINTERPRET_CAST_EXPR:
-    case CONST_CAST_EXPR:
-    case STATIC_CAST_EXPR:
-    case DYNAMIC_CAST_EXPR:
-    case ARROW_EXPR:
-    case DOTSTAR_EXPR:
-    case TYPEID_EXPR:
-    case PSEUDO_DTOR_EXPR:
-      if (!fn)
-       return error_mark_node;
-      break;
-
     default:
       break;
     }
@@ -7938,35 +7947,41 @@ static tree
   return NULL_TREE;
 }
 
-/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
-   BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T,
-   call FN with the parameter and the DATA.
-   If FN returns nonzero, the iteration is terminated, and
-   for_each_template_parm returns 1.  Otherwise, the iteration
-   continues.  If FN never returns a nonzero value, the value
-   returned by for_each_template_parm is 0.  If FN is NULL, it is
-   considered to be the function which always returns 1.
+/* Walk T looking for TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
+   BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.
 
+   If CHECK_TYPES, return 1 if any, 0 otherwise.
+
+   If FN is non-null, for each the iteration calls FN with the parameter
+   and the DATA.  If FN returns nonzero, the iteration is terminated,
+   and walk_template_parms returns 1.  Otherwise, the iteration continues.
+   If FN never returns a nonzero value, the value returned by
+   walk_template_parms is 0.  If FN is NULL, it is considered to be the
+   function which always returns 1.
+
    If INCLUDE_NONDEDUCED_P, then this routine will also visit template
    parameters that occur in non-deduced contexts.  When false, only
    visits those template parameters that can be deduced.  */
 
 static int
-for_each_template_parm (tree t, tree_fn_t fn, void* data,
-                       struct pointer_set_t *visited,
-                       bool include_nondeduced_p)
+walk_template_parms (tree t, tree_fn_t fn, void* data,
+                    struct pointer_set_t *visited,
+                    bool check_types, bool include_nondeduced_p)
 {
   struct pair_fn_data pfd;
   int result;
 
+  gcc_assert (!check_types || !fn);
+
   /* Set up.  */
   pfd.fn = fn;
   pfd.data = data;
+  pfd.check_types = check_types;
   pfd.include_nondeduced_p = include_nondeduced_p;
 
   /* Walk the tree.  (Conceptually, we would like to walk without
-     duplicates, but for_each_template_parm_r recursively calls
-     for_each_template_parm, so we would need to reorganize a fair
+     duplicates, but walk_template_parms_r recursively calls
+     walk_template_parms, so we would need to reorganize a fair
      bit to use walk_tree_without_duplicates, so we keep our own
      visited list.)  */
   if (visited)
@@ -7974,7 +7989,7 @@ static int
   else
     pfd.visited = pointer_set_create ();
   result = cp_walk_tree (&t,
-                        for_each_template_parm_r,
+                        walk_template_parms_r,
                         &pfd,
                         pfd.visited) != NULL_TREE;
 
@@ -8035,8 +8050,9 @@ uses_template_parms (tree t)
 int
 uses_template_parms_level (tree t, int level)
 {
-  return for_each_template_parm (t, template_parm_this_level_p, &level, NULL,
-                                /*include_nondeduced_p=*/true);
+  return walk_template_parms (t, template_parm_this_level_p, &level, NULL,
+                             /*check_types=*/false,
+                             /*include_nondeduced_p=*/true);
 }
 
 /* Returns TRUE iff INST is an instantiation we don't need to do in an
@@ -19744,6 +19760,27 @@ type_dependent_expression_p (tree expression)
   return (dependent_type_p (TREE_TYPE (expression)));
 }
 
+/* Returns TRUE if the EXPRESSION is instantiation-dependent, in the
+   sense defined by the ABI:
+
+   "An expression is instantiation-dependent if it is type-dependent
+   or value-dependent, or it has a subexpression that is type-dependent
+   or value-dependent."  */
+
+bool
+instantiation_dependent_expression_p (tree expression)
+{
+  if (!processing_template_decl)
+    return false;
+
+  if (expression == error_mark_node)
+    return false;
+
+  return walk_template_parms (expression, /*fn=*/NULL, NULL, NULL,
+                             /*check_types=*/true,
+                             /*include_nondeduced_p=*/true);
+}
+
 /* Like type_dependent_expression_p, but it also works while not processing
    a template definition, i.e. during substitution or mangling.  */
 
Index: cp/semantics.c
===================================================================
--- cp/semantics.c      (revision 187012)
+++ cp/semantics.c      (working copy)
@@ -5168,8 +5168,7 @@ finish_decltype_type (tree expr, bool id_expressio
       return error_mark_node;
     }
 
-  /* FIXME instantiation-dependent  */
-  if (type_dependent_expression_p (expr)
+  if (instantiation_dependent_expression_p (expr)
       /* In a template, a COMPONENT_REF has an IDENTIFIER_NODE for op1 even
         if it isn't dependent, so that we can check access control at
         instantiation time, so defer the decltype as well (PR 42277).  */
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 187012)
+++ cp/cp-tree.h        (working copy)
@@ -5363,6 +5363,7 @@ extern bool any_type_dependent_arguments_p      (c
 extern bool any_type_dependent_elements_p       (const_tree);
 extern bool type_dependent_expression_p_push   (tree);
 extern bool value_dependent_expression_p       (tree);
+extern bool instantiation_dependent_expression_p(tree);
 extern bool any_value_dependent_elements_p      (const_tree);
 extern bool dependent_omp_for_p                        (tree, tree, tree, 
tree);
 extern tree resolve_typename_type              (tree, bool);

Reply via email to