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 /gcc/testsuite/g++.dg/concepts | |
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.
Diffstat (limited to 'gcc/testsuite/g++.dg/concepts')
-rw-r--r-- | gcc/testsuite/g++.dg/concepts/diagnostic2.C | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/concepts/diagnostic3.C | 29 |
2 files changed, 59 insertions, 0 deletions
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" } +} |