tree ci = build_tree_list (t, info.context);
tree atom = build1 (ATOMIC_CONSTR, ci, map);
+
+ /* Remember whether the expression of this atomic constraint belongs to
+ a concept definition by inspecting in_decl, which should always be set
+ in this case either by norm_info::update_context (when recursing into a
+ concept-id during normalization) or by normalize_concept_definition
+ (when starting out with a concept-id). */
+ if (info.in_decl && concept_definition_p (info.in_decl))
+ ATOMIC_CONSTR_EXPR_FROM_CONCEPT_P (atom) = true;
+
if (!info.generate_diagnostics ())
{
/* Cache the ATOMIC_CONSTRs that we return, so that sat_hasher::equal
return boolean_true_node;
}
-/* Build a new template argument list with template arguments corresponding
- to the parameters used in an atomic constraint. */
+/* Build a new template argument vector corresponding to the parameter
+ mapping of the atomic constraint T, using arguments from ARGS. */
-tree
-get_mapped_args (tree map)
+static tree
+get_mapped_args (tree t, tree args)
{
+ tree map = ATOMIC_CONSTR_MAP (t);
+
/* No map, no arguments. */
if (!map)
return NULL_TREE;
- /* Find the mapped parameter with the highest level. */
- int count = 0;
- for (tree p = map; p; p = TREE_CHAIN (p))
- {
- int level;
- int index;
- template_parm_level_and_index (TREE_VALUE (p), &level, &index);
- if (level > count)
- count = level;
- }
+ /* Determine the depth of the resulting argument vector. */
+ int depth;
+ if (ATOMIC_CONSTR_EXPR_FROM_CONCEPT_P (t))
+ /* The expression of this atomic constraint comes from a concept definition,
+ whose template depth is always one, so the resulting argument vector
+ will also have depth one. */
+ depth = 1;
+ else
+ /* Otherwise, the expression of this atomic constraint comes from
+ the context of the constrained entity, whose template depth is that
+ of ARGS. */
+ depth = TMPL_ARGS_DEPTH (args);
/* Place each argument at its corresponding position in the argument
list. Note that the list will be sparse (not all arguments supplied),
but instantiation is guaranteed to only use the parameters in the
mapping, so null arguments would never be used. */
- auto_vec< vec<tree> > lists (count);
- lists.quick_grow_cleared (count);
+ auto_vec< vec<tree> > lists (depth);
+ lists.quick_grow_cleared (depth);
for (tree p = map; p; p = TREE_CHAIN (p))
{
int level;
/* Insert the argument into its corresponding position. */
vec<tree> &list = lists[level - 1];
if (index >= (int)list.length ())
- list.safe_grow_cleared (index + 1, true);
+ list.safe_grow_cleared (index + 1, /*exact=*/false);
list[index] = TREE_PURPOSE (p);
}
/* Build the new argument list. */
- tree args = make_tree_vec (lists.length ());
+ args = make_tree_vec (lists.length ());
for (unsigned i = 0; i != lists.length (); ++i)
{
vec<tree> &list = lists[i];
}
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args, 0);
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)
+ && TMPL_ARGS_DEPTH (args) == 1)
+ {
+ /* Get rid of the redundant outer TREE_VEC. */
+ tree level = TMPL_ARGS_LEVEL (args, 1);
+ ggc_free (args);
+ args = level;
+ }
+
return args;
}
}
/* Rebuild the argument vector from the parameter mapping. */
- args = get_mapped_args (map);
+ args = get_mapped_args (t, args);
/* Apply the parameter mapping (i.e., just substitute). */
tree expr = ATOMIC_CONSTR_EXPR (t);
if (!same_type_p (TREE_TYPE (result), boolean_type_node))
{
if (info.noisy ())
- diagnose_atomic_constraint (t, map, result, info);
+ diagnose_atomic_constraint (t, args, result, info);
return cache.save (inst_cache.save (error_mark_node));
}
}
result = satisfaction_value (result);
if (result == boolean_false_node && info.diagnose_unsatisfaction_p ())
- diagnose_atomic_constraint (t, map, result, info);
+ diagnose_atomic_constraint (t, args, result, info);
return cache.save (inst_cache.save (result));
}
}
}
-/* Diagnose a substitution failure in the atomic constraint T when applied
- with the instantiated parameter mapping MAP. */
+/* Diagnose a substitution failure in the atomic constraint T using ARGS. */
static void
-diagnose_atomic_constraint (tree t, tree map, tree result, sat_info info)
+diagnose_atomic_constraint (tree t, tree args, tree result, sat_info info)
{
/* If the constraint is already ill-formed, we've previously diagnosed
the reason. We should still say why the constraints aren't satisfied. */
/* Generate better diagnostics for certain kinds of expressions. */
tree expr = ATOMIC_CONSTR_EXPR (t);
STRIP_ANY_LOCATION_WRAPPER (expr);
- tree args = get_mapped_args (map);
switch (TREE_CODE (expr))
{
case TRAIT_EXPR:
IMPLICIT_CONV_EXPR_NONTYPE_ARG (in IMPLICIT_CONV_EXPR)
BASELINK_FUNCTIONS_MAYBE_INCOMPLETE_P (in BASELINK)
BIND_EXPR_VEC_DTOR (in BIND_EXPR)
+ ATOMIC_CONSTR_EXPR_FROM_CONCEPT_P (in ATOMIC_CONSTR)
2: IDENTIFIER_KIND_BIT_2 (in IDENTIFIER_NODE)
ICS_THIS_FLAG (in _CONV)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
#define ATOMIC_CONSTR_MAP_INSTANTIATED_P(NODE) \
TREE_LANG_FLAG_0 (ATOMIC_CONSTR_CHECK (NODE))
+/* Whether the expression for this atomic constraint belongs to a
+ concept definition. */
+#define ATOMIC_CONSTR_EXPR_FROM_CONCEPT_P(NODE) \
+ TREE_LANG_FLAG_1 (ATOMIC_CONSTR_CHECK (NODE))
+
/* The expression of an atomic constraint. */
#define ATOMIC_CONSTR_EXPR(NODE) \
CONSTR_EXPR (ATOMIC_CONSTR_CHECK (NODE))
extern tree tsubst_constraint (tree, tree, tsubst_flags_t, tree);
extern tree tsubst_constraint_info (tree, tree, tsubst_flags_t, tree);
extern tree tsubst_parameter_mapping (tree, tree, tsubst_flags_t, tree);
-extern tree get_mapped_args (tree);
struct processing_constraint_expression_sentinel
{