diff options
Diffstat (limited to 'gcc/cp/error.c')
-rw-r--r-- | gcc/cp/error.c | 202 |
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. */ |