aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/error.c')
-rw-r--r--gcc/cp/error.c202
1 files changed, 189 insertions, 13 deletions
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 5620134..1fd87d2 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -98,6 +98,7 @@ static void print_instantiation_full_context (diagnostic_context *);
static void print_instantiation_partial_context (diagnostic_context *,
struct tinst_level *,
location_t);
+static void maybe_print_constraint_context (diagnostic_context *);
static void cp_diagnostic_starter (diagnostic_context *, diagnostic_info *);
static void cp_print_error_function (diagnostic_context *, diagnostic_info *);
@@ -545,9 +546,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
case TEMPLATE_TYPE_PARM:
pp_cxx_cv_qualifier_seq (pp, t);
- if (tree c = PLACEHOLDER_TYPE_CONSTRAINTS (t))
- pp_cxx_constrained_type_spec (pp, c);
- else if (template_placeholder_p (t))
+ if (template_placeholder_p (t))
{
t = TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t));
pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
@@ -558,6 +557,9 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
else
pp_cxx_canonical_template_parameter
(pp, TEMPLATE_TYPE_PARM_INDEX (t));
+ /* If this is a constrained placeholder, add the requirements. */
+ if (tree c = PLACEHOLDER_TYPE_CONSTRAINTS (t))
+ pp_cxx_constrained_type_spec (pp, c);
break;
/* This is not always necessary for pointers and such, but doing this
@@ -1284,6 +1286,15 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags)
dump_template_decl (pp, t, flags);
break;
+ case CONCEPT_DECL:
+ pp_cxx_ws_string (pp, "concept");
+ dump_decl_name (pp, DECL_NAME (t), flags);
+ break;
+
+ case WILDCARD_DECL:
+ pp_string (pp, "<wildcard>");
+ break;
+
case TEMPLATE_ID_EXPR:
{
tree name = TREE_OPERAND (t, 0);
@@ -1448,7 +1459,9 @@ dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
else if (DECL_TEMPLATE_RESULT (t)
&& (VAR_P (DECL_TEMPLATE_RESULT (t))
/* Alias template. */
- || DECL_TYPE_TEMPLATE_P (t)))
+ || DECL_TYPE_TEMPLATE_P (t)
+ /* Concept definition. &*/
+ || TREE_CODE (DECL_TEMPLATE_RESULT (t)) == CONCEPT_DECL))
dump_decl (pp, DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
else
{
@@ -2082,6 +2095,7 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
case TEMPLATE_DECL:
case NAMESPACE_DECL:
case LABEL_DECL:
+ case WILDCARD_DECL:
case OVERLOAD:
case TYPE_DECL:
case IDENTIFIER_NODE:
@@ -2848,18 +2862,14 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
pp_cxx_nested_requirement (cxx_pp, t);
break;
- case PRED_CONSTR:
+ case ATOMIC_CONSTR:
case CHECK_CONSTR:
- case EXPR_CONSTR:
- case TYPE_CONSTR:
- case ICONV_CONSTR:
- case DEDUCT_CONSTR:
- case EXCEPT_CONSTR:
- case PARM_CONSTR:
case CONJ_CONSTR:
case DISJ_CONSTR:
- pp_cxx_constraint (cxx_pp, t);
- break;
+ {
+ pp_cxx_constraint (cxx_pp, t);
+ break;
+ }
case PLACEHOLDER_EXPR:
pp_string (pp, M_("*this"));
@@ -3326,6 +3336,7 @@ cp_diagnostic_starter (diagnostic_context *context,
cp_print_error_function (context, diagnostic);
maybe_print_instantiation_context (context);
maybe_print_constexpr_context (context);
+ maybe_print_constraint_context (context);
pp_set_prefix (context->printer, diagnostic_build_prefix (context,
diagnostic));
}
@@ -3650,6 +3661,171 @@ maybe_print_constexpr_context (diagnostic_context *context)
}
+static void
+print_location (diagnostic_context *context, location_t loc)
+{
+ expanded_location xloc = expand_location (loc);
+ if (context->show_column)
+ pp_verbatim (context->printer, _("%r%s:%d:%d:%R "),
+ "locus", xloc.file, xloc.line, xloc.column);
+ else
+ pp_verbatim (context->printer, _("%r%s:%d:%R "),
+ "locus", xloc.file, xloc.line);
+}
+
+/* Instantiate the concept check for the purpose of diagnosing an error. */
+
+static tree
+rebuild_concept_check (tree expr, tree map, tree args)
+{
+ /* Instantiate the parameter mapping for the template-id. */
+ map = tsubst_parameter_mapping (map, args, tf_none, NULL_TREE);
+ if (map == error_mark_node)
+ return error_mark_node;
+ args = get_mapped_args (map);
+
+ /* Rebuild the template id using substituted arguments. Substituting
+ directly through the expression will trigger recursive satisfaction,
+ so don't do that. */
+ tree id = unpack_concept_check (expr);
+ args = tsubst_template_args (TREE_OPERAND (id, 1), args, tf_none, NULL_TREE);
+ if (args == error_mark_node)
+ return error_mark_node;
+ return build_nt (TEMPLATE_ID_EXPR, TREE_OPERAND (id, 0), args);
+}
+
+static void
+print_constrained_decl_info (diagnostic_context *context, tree decl)
+{
+ print_location (context, DECL_SOURCE_LOCATION (decl));
+ pp_verbatim (context->printer, "required by the constraints of %q#D\n", decl);
+}
+
+static void
+print_concept_check_info (diagnostic_context *context, tree expr, tree map, tree args)
+{
+ gcc_assert (concept_check_p (expr));
+
+ tree id = unpack_concept_check (expr);
+ tree tmpl = TREE_OPERAND (id, 0);
+ if (OVL_P (tmpl))
+ tmpl = OVL_FIRST (tmpl);
+ tree check = rebuild_concept_check (expr, map, args);
+ if (check == error_mark_node)
+ check = expr;
+
+ print_location (context, DECL_SOURCE_LOCATION (tmpl));
+ pp_verbatim (context->printer, "required for the satisfaction of %qE\n", check);
+}
+
+/* Diagnose the entry point into the satisfaction error. Returns the next
+ context, if any. */
+
+static tree
+print_constraint_context_head (diagnostic_context *context, tree cxt, tree args)
+{
+ tree src = TREE_VALUE (cxt);
+ if (!src)
+ {
+ print_location (context, input_location);
+ pp_verbatim (context->printer, "required for constraint satisfaction\n");
+ return NULL_TREE;
+ }
+ if (DECL_P (src))
+ {
+ print_constrained_decl_info (context, src);
+ return NULL_TREE;
+ }
+ else
+ {
+ print_concept_check_info (context, src, TREE_PURPOSE (cxt), args);
+ return TREE_CHAIN (cxt);
+ }
+}
+
+static void
+print_requires_expression_info (diagnostic_context *context, tree constr, tree args)
+{
+
+ tree expr = ATOMIC_CONSTR_EXPR (constr);
+ tree map = ATOMIC_CONSTR_MAP (constr);
+ map = tsubst_parameter_mapping (map, args, tf_none, NULL_TREE);
+ if (map == error_mark_node)
+ return;
+ args = get_mapped_args (map);
+
+ print_location (context, cp_expr_loc_or_input_loc (expr));
+ pp_verbatim (context->printer, "in requirements ");
+
+ tree parms = TREE_OPERAND (expr, 0);
+ if (parms)
+ pp_verbatim (context->printer, "with ");
+ while (parms)
+ {
+ tree next = TREE_CHAIN (parms);
+
+ TREE_CHAIN (parms) = NULL_TREE;
+ cp_unevaluated u;
+ tree p = tsubst (parms, args, tf_none, NULL_TREE);
+ pp_verbatim (context->printer, "%q#D", p);
+ TREE_CHAIN (parms) = next;
+
+ if (next)
+ pp_separate_with_comma ((cxx_pretty_printer *)context->printer);
+
+ parms = next;
+ }
+
+ pp_verbatim (context->printer, "\n");
+}
+
+void
+maybe_print_single_constraint_context (diagnostic_context *context, tree failed)
+{
+ if (!failed)
+ return;
+
+ tree constr = TREE_VALUE (failed);
+ if (!constr || constr == error_mark_node)
+ return;
+ tree cxt = CONSTR_CONTEXT (constr);
+ if (!cxt)
+ return;
+ tree args = TREE_PURPOSE (failed);
+
+ /* Print the stack of requirements. */
+ cxt = print_constraint_context_head (context, cxt, args);
+ while (cxt && !DECL_P (TREE_VALUE (cxt)))
+ {
+ tree expr = TREE_VALUE (cxt);
+ tree map = TREE_PURPOSE (cxt);
+ print_concept_check_info (context, expr, map, args);
+ cxt = TREE_CHAIN (cxt);
+ }
+
+ /* For certain constraints, we can provide additional context. */
+ if (TREE_CODE (constr) == ATOMIC_CONSTR
+ && TREE_CODE (ATOMIC_CONSTR_EXPR (constr)) == REQUIRES_EXPR)
+ print_requires_expression_info (context, constr, args);
+}
+
+void
+maybe_print_constraint_context (diagnostic_context *context)
+{
+ if (!current_failed_constraint)
+ return;
+
+ tree cur = current_failed_constraint;
+
+ /* Recursively print nested contexts. */
+ current_failed_constraint = TREE_CHAIN (current_failed_constraint);
+ if (current_failed_constraint)
+ maybe_print_constraint_context (context);
+
+ /* Print this context. */
+ maybe_print_single_constraint_context (context, cur);
+}
+
/* Return true iff TYPE_A and TYPE_B are template types that are
meaningful to compare. */