aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/constraint.cc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2020-02-20 15:56:20 -0500
committerPatrick Palka <ppalka@redhat.com>2020-02-26 11:19:18 -0500
commit44f6b7fb574ff197443374dd042ca02ad91e1914 (patch)
treee8e12221b36d992696201f54936aa214c2590be3 /gcc/cp/constraint.cc
parent38e1002657828150b2cda9f80c1f752184286e80 (diff)
downloadgcc-44f6b7fb574ff197443374dd042ca02ad91e1914.zip
gcc-44f6b7fb574ff197443374dd042ca02ad91e1914.tar.gz
gcc-44f6b7fb574ff197443374dd042ca02ad91e1914.tar.bz2
c++: Some improvements to concept diagnostics
This patch improves our concept diagnostics in two ways. First, it sets a more precise location for the constraint expressions built in finish_constraint_binary_op. As a result, when a disjunction is unsatisfied we now print e.g. .../include/bits/range_access.h:467:2: note: neither operand of the disjunction is satisfied 466 | requires is_bounded_array_v<remove_reference_t<_Tp>> || __member_end<_Tp> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 467 | || __adl_end<_Tp> | ^~~~~~~~~~~~~~~~~ instead of .../include/bits/range_access.h:467:2: note: neither operand of the disjunction is satisfied 467 | || __adl_end<_Tp> | ^~ Second, this patch changes diagnose_atomic_constraint to print unsatisfied atomic constraint expressions with their template arguments. So e.g. we now print cpp2a/concepts-pr67719.C:9:8: note: the expression ‘(... &&(C<Tx>)()) [with Tx = {int, long int, void}]’ evaluated to ‘false’ instead of cpp2a/concepts-pr67719.C:9:8: note: the expression ‘(... &&(C<Tx>)())’ evaluated to ‘false’ Tested on x86_64-pc-linux-gnu, and verified that all the diagnostics emitted in our concept tests are no worse with this patch. gcc/cp/ChangeLog: * constraint.cc (finish_constraint_binary_op): Set expr's location range to the range of its operands. (satisfy_atom): Pass MAP instead of ARGS to diagnose_atomic_constraint. (diagnose_trait_expr): Take the instantiated parameter mapping MAP instead of the corresponding template arguments ARGS and adjust body accordingly. (diagnose_requires_expr): Likewise. (diagnose_atomic_constraint): Likewise. When printing an atomic constraint expression, print the instantiated parameter mapping alongside it. * cxx-pretty-print.cc (cxx_pretty_printer::expression) [NONTYPE_ARGUMENT_PACK]: Print braces around a NONTYPE_ARGUMENT_PACK. (cxx_pretty_printer::type_id): Handle TYPE_ARGUMENT_PACK. gcc/testsuite/ChangeLog: * g++.dg/concepts/diagnostic2.C: New test. * g++.dg/concepts/diagnostic3.C: New test.
Diffstat (limited to 'gcc/cp/constraint.cc')
-rw-r--r--gcc/cp/constraint.cc33
1 files changed, 19 insertions, 14 deletions
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 58044cd..4bb4a3f 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -155,14 +155,14 @@ finish_constraint_binary_op (location_t loc,
if (!check_constraint_operands (loc, lhs, rhs))
return error_mark_node;
tree overload;
- tree expr = build_x_binary_op (loc, code,
- lhs, TREE_CODE (lhs),
- rhs, TREE_CODE (rhs),
- &overload, tf_none);
+ cp_expr expr = build_x_binary_op (loc, code,
+ lhs, TREE_CODE (lhs),
+ rhs, TREE_CODE (rhs),
+ &overload, tf_none);
/* When either operand is dependent, the overload set may be non-empty. */
if (expr == error_mark_node)
return error_mark_node;
- SET_EXPR_LOCATION (expr, loc);
+ expr.set_range (lhs.get_start (), rhs.get_finish ());
return expr;
}
@@ -2547,7 +2547,7 @@ satisfy_atom (tree t, tree args, subst_info info)
/* Compute the value of the constraint. */
result = satisfaction_value (cxx_constant_value (result));
if (result == boolean_false_node && info.noisy ())
- diagnose_atomic_constraint (t, args, info);
+ diagnose_atomic_constraint (t, map, info);
return cache.save (result);
}
@@ -3056,9 +3056,10 @@ get_constraint_error_location (tree t)
/* Emit a diagnostic for a failed trait. */
void
-diagnose_trait_expr (tree expr, tree args)
+diagnose_trait_expr (tree expr, tree map)
{
location_t loc = cp_expr_location (expr);
+ tree args = get_mapped_args (map);
/* Build a "fake" version of the instantiated trait, so we can
get the instantiated types from result. */
@@ -3271,11 +3272,12 @@ diagnose_requirement (tree req, tree args, tree in_decl)
}
static void
-diagnose_requires_expr (tree expr, tree args, tree in_decl)
+diagnose_requires_expr (tree expr, tree map, tree in_decl)
{
local_specialization_stack stack (lss_copy);
tree parms = TREE_OPERAND (expr, 0);
tree body = TREE_OPERAND (expr, 1);
+ tree args = get_mapped_args (map);
cp_unevaluated u;
subst_info info (tf_warning_or_error, NULL_TREE);
@@ -3292,11 +3294,11 @@ diagnose_requires_expr (tree expr, tree args, tree in_decl)
}
}
-/* Diagnose a substitution failure in the atomic constraint T. Note that
- ARGS have been previously instantiated through the parameter map. */
+/* Diagnose a substitution failure in the atomic constraint T when applied
+ with the instantiated parameter mapping MAP. */
static void
-diagnose_atomic_constraint (tree t, tree args, subst_info info)
+diagnose_atomic_constraint (tree t, tree map, subst_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. */
@@ -3320,17 +3322,20 @@ diagnose_atomic_constraint (tree t, tree args, subst_info info)
switch (TREE_CODE (expr))
{
case TRAIT_EXPR:
- diagnose_trait_expr (expr, args);
+ diagnose_trait_expr (expr, map);
break;
case REQUIRES_EXPR:
- diagnose_requires_expr (expr, args, info.in_decl);
+ diagnose_requires_expr (expr, map, info.in_decl);
break;
case INTEGER_CST:
/* This must be either 0 or false. */
inform (loc, "%qE is never satisfied", expr);
break;
default:
- inform (loc, "the expression %qE evaluated to %<false%>", expr);
+ tree a = copy_node (t);
+ ATOMIC_CONSTR_MAP (a) = map;
+ inform (loc, "the expression %qE evaluated to %<false%>", a);
+ ggc_free (a);
}
}