diff options
author | Patrick Palka <ppalka@redhat.com> | 2020-02-20 15:56:20 -0500 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2020-02-26 11:19:18 -0500 |
commit | 44f6b7fb574ff197443374dd042ca02ad91e1914 (patch) | |
tree | e8e12221b36d992696201f54936aa214c2590be3 | |
parent | 38e1002657828150b2cda9f80c1f752184286e80 (diff) | |
download | gcc-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.
-rw-r--r-- | gcc/cp/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/constraint.cc | 33 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/concepts/diagnostic2.C | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/concepts/diagnostic3.C | 29 |
6 files changed, 116 insertions, 14 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d34730c..5962981 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2020-02-26 Patrick Palka <ppalka@redhat.com> + + * 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. + 2020-02-26 Marek Polacek <polacek@redhat.com> PR c++/93676 - value-init crash in template. 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); } } diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 9e0c5fc..397bdbf 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -1214,12 +1214,14 @@ cxx_pretty_printer::expression (tree t) { tree args = ARGUMENT_PACK_ARGS (t); int i, len = TREE_VEC_LENGTH (args); + pp_cxx_left_brace (this); for (i = 0; i < len; ++i) { if (i > 0) pp_cxx_separate_with (this, ','); expression (TREE_VEC_ELT (args, i)); } + pp_cxx_right_brace (this); } break; @@ -1839,6 +1841,21 @@ cxx_pretty_printer::type_id (tree t) pp_cxx_ws_string (this, "..."); break; + case TYPE_ARGUMENT_PACK: + { + tree args = ARGUMENT_PACK_ARGS (t); + int len = TREE_VEC_LENGTH (args); + pp_cxx_left_brace (this); + for (int i = 0; i < len; ++i) + { + if (i > 0) + pp_cxx_separate_with (this, ','); + type_id (TREE_VEC_ELT (args, i)); + } + pp_cxx_right_brace (this); + } + break; + default: c_pretty_printer::type_id (t); break; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 572989b..662ffbf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-02-26 Patrick Palka <ppalka@redhat.com> + + * g++.dg/concepts/diagnostic2.C: New test. + * g++.dg/concepts/diagnostic3.C: New test. + 2020-02-26 Marek Polacek <polacek@redhat.com> PR c++/93676 - value-init crash in template. diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic2.C b/gcc/testsuite/g++.dg/concepts/diagnostic2.C new file mode 100644 index 0000000..ce51b71 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/diagnostic2.C @@ -0,0 +1,30 @@ +// { dg-do compile { target c++2a } } +// { dg-options "-fdiagnostics-show-caret" } + +template<typename T> + inline constexpr bool foo_v = false; + +template<typename T> + concept foo = foo_v<T> || foo_v<T&>; // { dg-message "neither operand" } +/* { dg-begin-multiline-output "" } + concept foo = foo_v<T> || foo_v<T&>; + ~~~~~~~~~^~~~~~~~~~~~ + { dg-end-multiline-output "" } */ + +template<typename T> + requires foo<T> + void bar(); +/* { dg-begin-multiline-output "" } + void bar(); + { dg-end-multiline-output "" } */ +/* { dg-prune-output "~" } */ + +void +baz() +{ + bar<int>(); // { dg-error "unsatisfied constraints" } +/* { dg-begin-multiline-output "" } + bar<int>(); + ^ + { dg-end-multiline-output "" } */ +} diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic3.C b/gcc/testsuite/g++.dg/concepts/diagnostic3.C new file mode 100644 index 0000000..b4c7540 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/diagnostic3.C @@ -0,0 +1,29 @@ +// { dg-do compile { target c++2a } } + +template<typename T> + inline constexpr bool foo_v = false; + +template<typename T> + concept foo = (bool)(foo_v<T> | foo_v<T&>); + +template<typename... Ts> +requires (foo<Ts> && ...) +void +bar() // { dg-message "with Ts = .int, char... evaluated to .false." } +{ } + +template<int> +struct S { }; + +template<int... Is> +requires (foo<S<Is>> && ...) +void +baz() // { dg-message "with Is = .2, 3, 4... evaluated to .false." } +{ } + +void +baz() +{ + bar<int, char>(); // { dg-error "unsatisfied constraints" } + baz<2,3,4>(); // { dg-error "unsatisfied constraints" } +} |