[gcc(refs/users/ppalka/heads/wip)] c++: flatten parameter mapping
Patrick Palka
ppalka@gcc.gnu.org
Mon Nov 2 21:31:00 GMT 2020
https://gcc.gnu.org/g:478c9d57b02c0b31321b3a596d38688739817fc4
commit 478c9d57b02c0b31321b3a596d38688739817fc4
Author: Patrick Palka <ppalka@redhat.com>
Date: Thu Oct 29 11:00:43 2020 -0400
c++: flatten parameter mapping
gcc/cp/ChangeLog:
* constraint.cc (build_parameter_mapping):
(parameter_mapping_equivalent_p):
(hash_atomic_constraint):
(tsubst_parameter_mapping):
(satisfy_atom):
Diff:
---
gcc/cp/constraint.cc | 181 +++++++++++++++++++++++++++++++--------------------
1 file changed, 111 insertions(+), 70 deletions(-)
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index b6f6f0d02a5..6223d864eb6 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -579,9 +579,57 @@ build_parameter_mapping (tree expr, tree args, tree decl)
ctx_parms = current_template_parms;
}
+ while (ctx_parms && NUM_TMPL_ARGS (TREE_VALUE (ctx_parms)) == 0)
+ ctx_parms = TREE_CHAIN (ctx_parms);
+
tree parms = find_template_parameters (expr, ctx_parms);
- tree map = map_arguments (parms, args);
- return map;
+ if (!parms)
+ return NULL_TREE;
+
+ tree mapping;
+ int depth = TMPL_PARMS_DEPTH (ctx_parms);
+ if (depth == 1)
+ mapping = make_tree_vec (0);
+ else
+ {
+ mapping = make_tree_vec (depth);
+ TREE_VEC_ELT (mapping, 0) = make_tree_vec (0);
+ gcc_assert (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (mapping));
+ }
+
+ for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
+ {
+ int level, index;
+ template_parm_level_and_index (TREE_VALUE (parm), &level, &index);
+
+ if (tree& lvl = TMPL_ARGS_LEVEL (mapping, level))
+ {
+ int curlen = NUM_TMPL_ARGS (lvl);
+ int newlen = index + 1;
+ if (curlen < newlen)
+ {
+ lvl = grow_tree_vec (lvl, newlen);
+ for (int i = curlen; i < newlen; i++)
+ TREE_VEC_ELT (lvl, i) = NULL_TREE;
+ if (depth == 1)
+ mapping = lvl;
+ }
+ }
+ else
+ lvl = make_tree_vec (index + 1);
+
+ if (args)
+ TMPL_ARG (mapping, level, index) = TMPL_ARG (args, level, index);
+ else
+ {
+ tree header = ctx_parms;
+ while (TREE_INT_CST_LOW (TREE_PURPOSE (header)) != level)
+ header = TREE_CHAIN (header);
+ TMPL_ARG (mapping, level, index)
+ = template_parm_to_arg (TREE_VEC_ELT (TREE_VALUE (header), index));
+ }
+ }
+ return mapping;
}
/* True if the parameter mappings of two atomic constraints are equivalent. */
@@ -591,16 +639,7 @@ parameter_mapping_equivalent_p (tree t1, tree t2)
{
tree map1 = ATOMIC_CONSTR_MAP (t1);
tree map2 = ATOMIC_CONSTR_MAP (t2);
- while (map1 && map2)
- {
- tree arg1 = TREE_PURPOSE (map1);
- tree arg2 = TREE_PURPOSE (map2);
- if (!template_args_equal (arg1, arg2))
- return false;
- map1 = TREE_CHAIN (map1);
- map2 = TREE_CHAIN (map2);
- }
- return true;
+ return template_args_equal (map1, map2);
}
/* Provides additional context for normalization. */
@@ -965,14 +1004,7 @@ hash_atomic_constraint (tree t)
hashval_t val = htab_hash_pointer (ATOMIC_CONSTR_EXPR (t));
/* Hash the targets of the parameter map. */
- tree p = ATOMIC_CONSTR_MAP (t);
- while (p)
- {
- val = iterative_hash_template_arg (TREE_PURPOSE (p), val);
- p = TREE_CHAIN (p);
- }
-
- return val;
+ return iterative_hash_template_arg (ATOMIC_CONSTR_MAP (t), val);
}
namespace inchash
@@ -2212,53 +2244,65 @@ tsubst_parameter_mapping (tree map, tree args, subst_info info)
tsubst_flags_t complain = info.complain;
tree in_decl = info.in_decl;
- tree result = NULL_TREE;
- for (tree p = map; p; p = TREE_CHAIN (p))
+ tree result;
+ int depth = TMPL_ARGS_DEPTH (map);
+ if (depth == 1)
+ result = make_tree_vec (TREE_VEC_LENGTH (map));
+ else
{
- if (p == error_mark_node)
- return error_mark_node;
- tree parm = TREE_VALUE (p);
- tree arg = TREE_PURPOSE (p);
- tree new_arg = NULL_TREE;
- if (TYPE_P (arg))
- {
- /* If a template parameter is declared with a placeholder, we can
- get those in the argument list if decltype is applied to the
- placeholder. For example:
-
- template<auto T>
- requires C<decltype(T)>
- void f() { }
-
- The normalized argument for C will be an auto type, so we'll
- need to deduce the actual argument from the corresponding
- initializer (whatever argument is provided for T), and use
- that result in the instantiated parameter mapping. */
- if (tree auto_node = type_uses_auto (arg))
- {
- int level;
- int index;
- template_parm_level_and_index (parm, &level, &index);
- tree init = TMPL_ARG (args, level, index);
- new_arg = do_auto_deduction (arg, init, auto_node,
- complain, adc_variable_type,
- make_tree_vec (0));
- }
- }
- else if (ARGUMENT_PACK_P (arg))
- new_arg = tsubst_argument_pack (arg, args, complain, in_decl);
- if (!new_arg)
- {
- new_arg = tsubst_template_arg (arg, args, complain, in_decl);
- if (TYPE_P (new_arg))
- new_arg = canonicalize_type_argument (new_arg, complain);
- }
- if (new_arg == error_mark_node)
- return error_mark_node;
-
- result = tree_cons (new_arg, parm, result);
+ result = make_tree_vec (depth);
+ for (int i = 1; i <= depth; i++)
+ if (tree level = TMPL_ARGS_LEVEL (map, i))
+ TREE_VEC_ELT (result, i - 1) = make_tree_vec (NUM_TMPL_ARGS (level));
}
- return nreverse (result);
+ for (int i = 1; i <= depth; i++)
+ if (tree level = TMPL_ARGS_LEVEL (map, i))
+ {
+ int nargs = NUM_TMPL_ARGS (level);
+ for (int j = 0; j < nargs; j++)
+ {
+ tree arg = TMPL_ARG (map, i, j);
+ tree new_arg = NULL_TREE;
+ if (!arg)
+ continue;
+ else if (TYPE_P (arg))
+ {
+ /* If a template parameter is declared with a placeholder, we
+ can get those in the argument list if decltype is applied to
+ the placeholder. For example:
+
+ template<auto T>
+ requires C<decltype(T)>
+ void f() { }
+
+ The normalized argument for C will be an auto type, so we'll
+ need to deduce the actual argument from the corresponding
+ initializer (whatever argument is provided for T), and use
+ that result in the instantiated parameter mapping. */
+ if (tree auto_node = type_uses_auto (arg))
+ {
+ tree init = TMPL_ARG (args, i, j);
+ new_arg = do_auto_deduction (arg, init, auto_node,
+ complain, adc_variable_type,
+ make_tree_vec (0));
+ }
+ }
+ else if (ARGUMENT_PACK_P (arg))
+ new_arg = tsubst_argument_pack (arg, args, complain, in_decl);
+ if (!new_arg)
+ {
+ new_arg = tsubst_template_arg (arg, args, complain, in_decl);
+ if (TYPE_P (new_arg))
+ new_arg = canonicalize_type_argument (new_arg, complain);
+ }
+ if (new_arg == error_mark_node)
+ return error_mark_node;
+
+ TMPL_ARG (result, i, j) = new_arg;
+ }
+ }
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (result, 0);
+ return result;
}
tree
@@ -2583,18 +2627,15 @@ satisfy_atom (tree t, tree args, subst_info info)
return cache.save (boolean_false_node);
}
- /* Rebuild the argument vector from the parameter mapping. */
- args = get_mapped_args (map);
-
/* Apply the parameter mapping (i.e., just substitute). */
tree expr = ATOMIC_CONSTR_EXPR (t);
- tree result = tsubst_expr (expr, args, quiet.complain, quiet.in_decl, false);
+ tree result = tsubst_expr (expr, map, quiet.complain, quiet.in_decl, false);
if (result == error_mark_node)
{
/* If substitution results in an invalid type or expression, the constraint
is not satisfied. Replay the substitution. */
if (info.noisy ())
- tsubst_expr (expr, args, info.complain, info.in_decl, false);
+ tsubst_expr (expr, map, info.complain, info.in_decl, false);
return cache.save (boolean_false_node);
}
More information about the Gcc-cvs
mailing list