/* Returns the normal form of TMPL's definition. */
static tree
-normalize_concept_definition (tree tmpl)
+normalize_concept_definition (tree tmpl, bool diag = false)
{
- if (tree *p = hash_map_safe_get (normalized_map, tmpl))
- return *p;
+ if (!diag)
+ if (tree *p = hash_map_safe_get (normalized_map, tmpl))
+ return *p;
+
gcc_assert (concept_definition_p (tmpl));
if (OVL_P (tmpl))
tmpl = OVL_FIRST (tmpl);
tree args = generic_targs_for (tmpl);
tree def = get_concept_definition (DECL_TEMPLATE_RESULT (tmpl));
++processing_template_decl;
- norm_info info (tmpl, tf_none);
+ norm_info info (tmpl, diag ? tf_norm : tf_none);
tree norm = get_normalized_constraints (def, args, info);
--processing_template_decl;
- hash_map_safe_put<hm_ggc> (normalized_map, tmpl, norm);
+
+ if (!diag)
+ hash_map_safe_put<hm_ggc> (normalized_map, tmpl, norm);
+
return norm;
}
/* Cache the result of satisfy_atom. */
static GTY((deletable)) hash_table<sat_hasher> *sat_cache;
-/* Cache the result of constraints_satisfied_p. */
-static GTY((deletable)) hash_map<tree,bool> *decl_satisfied_cache;
+/* Cache the result of constraint_satisfaction_value. */
+static GTY((deletable)) hash_map<tree, tree> *decl_satisfied_cache;
static tree
get_satisfaction (tree constr, tree args)
return cache.save (boolean_false_node);
}
- location_t loc = cp_expr_location (expr);
+ location_t loc = cp_expr_loc_or_input_loc (expr);
/* [17.4.1.2] ... lvalue-to-value conversion is performed as necessary,
and EXPR shall be a constant expression of type bool. */
- result = force_rvalue (result, tf_error);
+ result = force_rvalue (result, info.complain);
if (result == error_mark_node)
- {
- if (info.noisy ())
- inform (loc, "cannot convert constraint to rvalue");
- return cache.save (error_mark_node);
- }
+ return cache.save (error_mark_node);
if (!same_type_p (TREE_TYPE (result), boolean_type_node))
{
if (info.noisy ())
- inform (loc, "constraint does not have type %<bool%>");
+ error_at (loc, "constraint does not have type %<bool%>");
return cache.save (error_mark_node);
}
static tree
satisfy_associated_constraints (tree t, tree args, subst_info info)
{
- /* If there are no constraints then this is trivially satisfied. */
+ /* If there are no constraints then this is trivially satisfied. */
if (!t)
return boolean_true_node;
satisfaction value. */
static tree
-satisfy_constraint_expression (tree expr, tree args, subst_info info)
+satisfy_constraint_expression (tree t, tree args, subst_info info)
{
- /* Normalize the expression before satisfaction testing. */
+ if (t == error_mark_node)
+ return error_mark_node;
+
+ gcc_assert (EXPR_P (t));
+
+ /* Get the normalized constraints. */
tree norm;
- if (args == NULL_TREE && concept_check_p (expr))
+ if (args == NULL_TREE && concept_check_p (t))
{
- tree id = unpack_concept_check (expr);
+ tree id = unpack_concept_check (t);
args = TREE_OPERAND (id, 1);
tree tmpl = get_concept_check_template (id);
- norm = normalize_concept_definition (tmpl);
+ norm = normalize_concept_definition (tmpl, info.noisy ());
}
else
- norm = normalize_constraint_expression (expr);
+ norm = normalize_constraint_expression (t, info.noisy ());
+
+ /* Perform satisfaction. */
return satisfy_constraint (norm, args, info);
}
-/* Used to evaluate concept checks and requires-expressions during
- constant expression evaluation. */
+/* Used only to evaluate requires-expressions during constant expression
+ evaluation. */
tree
satisfy_constraint_expression (tree expr)
return satisfy_constraint_expression (expr, NULL_TREE, info);
}
-/* True if T is satisfied for ARGS. */
-
-static bool
-constraint_expression_satisfied_p (tree t, tree args, subst_info info)
-{
- tree r = satisfy_constraint_expression (t, args, info);
- return r == boolean_true_node;
-}
-
-static bool
-constraints_satisfied_p (tree t, subst_info info)
+static tree
+satisfy_declaration_constraints (tree t, subst_info info)
{
- if (!DECL_P (t))
- return constraint_expression_satisfied_p (t, NULL_TREE, info);
+ gcc_assert (DECL_P (t));
/* For inherited constructors, consider the original declaration;
it has the correct template information attached. */
info.in_decl = t;
if (info.quiet ())
- if (bool *p = hash_map_safe_get (decl_satisfied_cache, t))
- return *p;
+ if (tree *result = hash_map_safe_get (decl_satisfied_cache, t))
+ return *result;
- /* Get the constraints to check for satisfaction. This depends
- on whether we're looking at a template specialization or not. */
+ /* Get the normalized constraints. */
tree norm = NULL_TREE;
tree args = NULL_TREE;
- tree ti = DECL_TEMPLATE_INFO (t);
- if (ti)
+ if (tree ti = DECL_TEMPLATE_INFO (t))
{
tree tmpl = TI_TEMPLATE (ti);
norm = normalize_template_requirements (tmpl, info.noisy ());
/* The initial parameter mapping is the complete set of
- template arguments substituted into the declaration. */
+ template arguments substituted into the declaration. */
args = TI_ARGS (ti);
}
else
norm = normalize_nontemplate_requirements (t, info.noisy ());
}
- bool r = true;
+ tree result = boolean_true_node;
if (norm)
{
push_access_scope (t);
- tree eval = satisfy_associated_constraints (norm, args, info);
+ result = satisfy_associated_constraints (norm, args, info);
pop_access_scope (t);
- r = (eval == boolean_true_node);
}
if (info.quiet ())
- hash_map_safe_put<hm_ggc> (decl_satisfied_cache, t, r);
-
- return r;
-}
+ hash_map_safe_put<hm_ggc> (decl_satisfied_cache, t, result);
-/* Returns true if the T's constraints are satisfied, of if T is an expression,
- if T is satisfied. This is used in cases where the arguments can be
- determined from the declaration or expression.
-
- Note that T is typically a template specialization. */
-
-bool
-constraints_satisfied_p (tree t)
-{
- subst_info info (tf_none, NULL_TREE);
- return constraints_satisfied_p (t, info);
+ return result;
}
-/* Returns true if the expression or constrained declaration T is
- satisfied by ARGS. In this case, we don't have a specialization
- where we can cache the results (e.g., alias templates). */
-
-static bool
-constraints_satisfied_p (tree t, tree args, subst_info info)
+static tree
+satisfy_declaration_constraints (tree t, tree args, subst_info info)
{
- if (!DECL_P (t))
- return constraint_expression_satisfied_p (t, args, info);
-
/* Update the declaration for diagnostics. */
info.in_decl = t;
{
tree pattern = DECL_TEMPLATE_RESULT (t);
push_access_scope (pattern);
- tree eval = satisfy_associated_constraints (norm, args, info);
+ tree result = satisfy_associated_constraints (norm, args, info);
pop_access_scope (pattern);
- return eval == boolean_true_node;
+ return result;
}
- return true;
+ return boolean_true_node;
}
+static tree
+constraint_satisfaction_value (tree t, tsubst_flags_t complain)
+{
+ subst_info info (complain, NULL_TREE);
+ if (DECL_P (t))
+ return satisfy_declaration_constraints (t, info);
+ else
+ return satisfy_constraint_expression (t, NULL_TREE, info);
+}
+
+static tree
+constraint_satisfaction_value (tree t, tree args, tsubst_flags_t complain)
+{
+ subst_info info (complain, NULL_TREE);
+ if (DECL_P (t))
+ return satisfy_declaration_constraints (t, args, info);
+ else
+ return satisfy_constraint_expression (t, args, info);
+}
+
+/* True iff the result of satisfying T is BOOLEAN_TRUE_NODE and false
+ otherwise, even in the case of errors. */
+
+bool
+constraints_satisfied_p (tree t)
+{
+ return constraint_satisfaction_value (t, tf_none) == boolean_true_node;
+}
+
+/* True iff the result of satisfying T with ARGS is BOOLEAN_TRUE_NODE
+ and false otherwise, even in the case of errors. */
+
bool
constraints_satisfied_p (tree t, tree args)
{
- subst_info info (tf_none, NULL);
- return constraints_satisfied_p (t, args, info);
+ return constraint_satisfaction_value (t, args, tf_none) == boolean_true_node;
}
-/* Evaluate a concept check of the form C<ARGS>, returning either TRUE
- or FALSE. If ARGS contains any template parameters, this returns the
- check. If satisfaction yields a hard error, diagnose the error. */
+/* Evaluate a concept check of the form C<ARGS>. This is only used for the
+ evaluation of template-ids as id-expressions. */
tree
evaluate_concept_check (tree check, tsubst_flags_t complain)
{
- /* FIXME we ought to be able to pass complain into subst_info rather
- than repeat satisfaction, but currently that will complain about
- non-satisfaction as well as errors. */
if (check == error_mark_node)
return error_mark_node;
gcc_assert (concept_check_p (check));
- subst_info info (tf_none, NULL_TREE);
- tree result = satisfy_constraint_expression (check, NULL_TREE, info);
+ /* Check for satisfaction without diagnostics. */
+ subst_info quiet (tf_none, NULL_TREE);
+ tree result = satisfy_constraint_expression (check, NULL_TREE, quiet);
if (result == error_mark_node && (complain & tf_error))
- {
- location_t loc = cp_expr_loc_or_input_loc (check);
- error_at (loc, "concept satisfaction failed");
- info.complain = complain;
- satisfy_constraint_expression (check, NULL_TREE, info);
- }
-
+ {
+ /* Replay the error with re-normalized requirements. */
+ subst_info noisy (tf_warning_or_error, NULL_TREE);
+ satisfy_constraint_expression (check, NULL_TREE, noisy);
+ }
return result;
}
}
}
+GTY(()) tree current_failed_constraint;
+
diagnosing_failed_constraint::
diagnosing_failed_constraint (tree t, tree args, bool diag)
: diagnosing_error (diag)
inform (loc, "constraints not satisfied");
/* Replay satisfaction, but diagnose errors. */
- subst_info info (tf_warning_or_error, NULL_TREE);
if (!args)
- constraints_satisfied_p (t, info);
+ constraint_satisfaction_value (t, tf_warning_or_error);
else
- constraints_satisfied_p (t, args, info);
+ constraint_satisfaction_value (t, args, tf_warning_or_error);
}
#include "gt-cp-constraint.h"