On 05/01/2012 10:06 PM, Paolo Carlini wrote:
I'm not 100% sure to understand the last two comments. I'm removing
completely the latter cases and changing the former like the below.
Note that the way I handle fn in walk_template_parms implies that when
check_types is true then pfd->fn is always NULL in
walk_template_parms_r.
The below is a variant which uses pfd->check_types for INDIRECT_REF and
COMPONENT_REF, consistently with other cases above and of course also works.
In fact, the reason why I'm still a bit confused about some of the cases
of this switch, is that I'm not sure to understand what it could mean to
call walk_template_parms with fn NULL and check_types false.
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,16 +7752,17 @@ 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;
@@ -7768,8 +7771,9 @@ static tree
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 +7787,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 +7832,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 +7846,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 +7901,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 +7912,36 @@ 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;
+ 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 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))
+ 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 +7950,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 nonnull, 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;
/* Set up. */
- pfd.fn = fn;
+ /* When check_types is true, fn plays no role, thus make sure is NULL,
+ which simplifies a bit walk_template_parms_r. */
+ pfd.fn = check_types ? NULL : 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 +7992,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 +8053,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 +19763,30 @@ 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;
+
+ if (!TREE_TYPE (expression))
+ return true;
+
+ 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);