On 05/02/2012 05:01 AM, Paolo Carlini wrote:
Anyway, the attached appear to also pass the testsuite, I could test it more completely tomorrow. If the FIELD_DECL bits seem safe to have... ;)
Now fully booted and tested.
I also booted and tested a variant, attached, which changes finish_static_assert to also use instantiation_dependent_expression_p and also passes testing: nice, between front-end and library we stress the new function quite a bit more.
Paolo. /////////////////////
Index: cp/pt.c =================================================================== --- cp/pt.c (revision 187039) +++ 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,48 @@ 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)) + case FIELD_DECL: + if ((TREE_CODE (t) == FIELD_DECL + || DECL_LANG_SPECIFIC (t)) && 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; /* 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 +7909,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 +7920,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 +7949,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 +7991,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 +8052,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 +19762,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 187039) +++ cp/semantics.c (working copy) @@ -5094,8 +5094,7 @@ finish_static_assert (tree condition, tree message if (check_for_bare_parameter_packs (condition)) condition = error_mark_node; - if (type_dependent_expression_p (condition) - || value_dependent_expression_p (condition)) + if (instantiation_dependent_expression_p (condition)) { /* We're in a template; build a STATIC_ASSERT and put it in the right place. */ @@ -5168,8 +5167,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 187039) +++ 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);