Message ID | 20200309222358.688229-2-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | [1/2] c++: Replay errors during diagnosis of constraint satisfaction failures | expand |
On Mon, 9 Mar 2020, Patrick Palka wrote: > The first patch tries to avoid changing our current default diagnostics. But > for the sake of consistency we arguably should also respect > current_constraint_diagnosis_depth in diagnose_compound_requirement() like we do > in the other error-replaying diagnostic routine. But doing so would be a change > to our default diagnostics behavior, so the change has been split out into this > separate patch for separate consideration. Ping. Here's a rebased version of this patch. -- >8 -- gcc/cp/ChangeLog: * constraint.cc (diagnose_compound_requirement): When diagnosing a compound requirement, maybe replay the satisfaction failure, subject to the current diagnosis depth. gcc/testsuite/ChangeLog: * g++.dg/concepts/diagnostic1.C: Pass -fconcepts-diagnostics-depth=2. * g++.dg/concepts/diagnostic5.C: Adjust expected diagnostics. * g++.dg/cpp2a/concepts-requires5.C: Pass -fconcepts-diagnostics-depth=2. --- gcc/cp/constraint.cc | 28 +++++++++++++------ gcc/testsuite/g++.dg/concepts/diagnostic1.C | 1 + gcc/testsuite/g++.dg/concepts/diagnostic5.C | 5 +--- gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C | 1 + .../g++.dg/cpp2a/concepts-requires5.C | 2 +- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 76c520318c3..571c7cbdd38 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -3308,20 +3308,30 @@ diagnose_compound_requirement (tree req, tree args, tree in_decl) if (!type_deducible_p (expr, type, placeholder, args, quiet)) { tree orig_expr = TREE_OPERAND (req, 0); - inform (loc, "%qE does not satisfy return-type-requirement", - orig_expr); - - /* Further explain the reason for the error. */ - type_deducible_p (expr, type, placeholder, args, noisy); + if (diagnosing_failed_constraint::replay_errors_p ()) + { + inform (loc, + "%qE does not satisfy return-type-requirement, " + "because", orig_expr); + /* Further explain the reason for the error. */ + type_deducible_p (expr, type, placeholder, args, noisy); + } + else + inform (loc, "%qE does not satisfy return-type-requirement", + orig_expr); } } else if (!expression_convertible_p (expr, type, quiet)) { tree orig_expr = TREE_OPERAND (req, 0); - inform (loc, "cannot convert %qE to %qT", orig_expr, type); - - /* Further explain the reason for the error. */ - expression_convertible_p (expr, type, noisy); + if (diagnosing_failed_constraint::replay_errors_p ()) + { + inform (loc, "cannot convert %qE to %qT because", orig_expr, type); + /* Further explain the reason for the error. */ + expression_convertible_p (expr, type, noisy); + } + else + inform (loc, "cannot convert %qE to %qT", orig_expr, type); } } } diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic1.C b/gcc/testsuite/g++.dg/concepts/diagnostic1.C index 7da08db2792..c6589e2e671 100644 --- a/gcc/testsuite/g++.dg/concepts/diagnostic1.C +++ b/gcc/testsuite/g++.dg/concepts/diagnostic1.C @@ -1,6 +1,7 @@ // PR c++/67159 // { dg-do compile { target c++17_only } } // { dg-options "-fconcepts" } +// { dg-additional-options "-fconcepts-diagnostics-depth=2" } template <class T, class U> concept bool SameAs = __is_same_as(T, U); diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic5.C b/gcc/testsuite/g++.dg/concepts/diagnostic5.C index 2641dc18423..0d890d6f548 100644 --- a/gcc/testsuite/g++.dg/concepts/diagnostic5.C +++ b/gcc/testsuite/g++.dg/concepts/diagnostic5.C @@ -4,8 +4,7 @@ template<typename T> concept c1 = requires { typename T::blah; }; // { dg-message "satisfaction of .c1<T>. .with T = char." "" { target *-*-* } .-1 } -// { dg-message "satisfaction of .c1<char\\*>." "" { target *-*-* } .-2 } -// { dg-message ".typename T::blah. is invalid" "" { target *-*-* } .-3 } +// { dg-message ".typename T::blah. is invalid" "" { target *-*-* } .-2 } template<typename T> concept c2 = requires (T x) { *x; }; @@ -27,8 +26,6 @@ template<typename T> concept c5 = requires (T x) { { &x } -> c1; }; // { dg-message "satisfaction of .c5<T>. .with T = char." "" { target *-*-* } .-1 } // { dg-message "in requirements with .char x." "" { target *-*-* } .-2 } -// { dg-message "does not satisfy return-type-requirement" "" { target *-*-* } .-3 } -// { dg-error "deduced expression type does not satisfy" "" { target *-*-* } .-4 } template<typename T> requires (c1<T> || c2<T>) || (c3<T> || c4<T>) || c5<T> // { dg-message "49: no operand" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C index 4d521c30748..4e2d13f8eb3 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C @@ -1,5 +1,6 @@ // PR c++/67240 // { dg-do compile { target c++2a } } +// { dg-additional-options "-fconcepts-diagnostics-depth=2" } template <class T, class U> concept Same = __is_same_as(T,U); diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C index 133d29e45a4..2f912b13d6a 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++2a } } -// { dg-additional-options -fconcepts-ts } +// { dg-additional-options "-fconcepts-ts -fconcepts-diagnostics-depth=2" } // Test conversion requirements (not in C++20)
On 3/27/20 12:20 AM, Patrick Palka wrote: > On Mon, 9 Mar 2020, Patrick Palka wrote: > >> The first patch tries to avoid changing our current default diagnostics. But >> for the sake of consistency we arguably should also respect >> current_constraint_diagnosis_depth in diagnose_compound_requirement() like we do >> in the other error-replaying diagnostic routine. But doing so would be a change >> to our default diagnostics behavior, so the change has been split out into this >> separate patch for separate consideration. > > Ping. Here's a rebased version of this patch. OK. > -- >8 -- > > gcc/cp/ChangeLog: > > * constraint.cc (diagnose_compound_requirement): When diagnosing a > compound requirement, maybe replay the satisfaction failure, subject to > the current diagnosis depth. > > gcc/testsuite/ChangeLog: > > * g++.dg/concepts/diagnostic1.C: Pass -fconcepts-diagnostics-depth=2. > * g++.dg/concepts/diagnostic5.C: Adjust expected diagnostics. > * g++.dg/cpp2a/concepts-requires5.C: Pass > -fconcepts-diagnostics-depth=2. > --- > gcc/cp/constraint.cc | 28 +++++++++++++------ > gcc/testsuite/g++.dg/concepts/diagnostic1.C | 1 + > gcc/testsuite/g++.dg/concepts/diagnostic5.C | 5 +--- > gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C | 1 + > .../g++.dg/cpp2a/concepts-requires5.C | 2 +- > 5 files changed, 23 insertions(+), 14 deletions(-) > > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc > index 76c520318c3..571c7cbdd38 100644 > --- a/gcc/cp/constraint.cc > +++ b/gcc/cp/constraint.cc > @@ -3308,20 +3308,30 @@ diagnose_compound_requirement (tree req, tree args, tree in_decl) > if (!type_deducible_p (expr, type, placeholder, args, quiet)) > { > tree orig_expr = TREE_OPERAND (req, 0); > - inform (loc, "%qE does not satisfy return-type-requirement", > - orig_expr); > - > - /* Further explain the reason for the error. */ > - type_deducible_p (expr, type, placeholder, args, noisy); > + if (diagnosing_failed_constraint::replay_errors_p ()) > + { > + inform (loc, > + "%qE does not satisfy return-type-requirement, " > + "because", orig_expr); > + /* Further explain the reason for the error. */ > + type_deducible_p (expr, type, placeholder, args, noisy); > + } > + else > + inform (loc, "%qE does not satisfy return-type-requirement", > + orig_expr); > } > } > else if (!expression_convertible_p (expr, type, quiet)) > { > tree orig_expr = TREE_OPERAND (req, 0); > - inform (loc, "cannot convert %qE to %qT", orig_expr, type); > - > - /* Further explain the reason for the error. */ > - expression_convertible_p (expr, type, noisy); > + if (diagnosing_failed_constraint::replay_errors_p ()) > + { > + inform (loc, "cannot convert %qE to %qT because", orig_expr, type); > + /* Further explain the reason for the error. */ > + expression_convertible_p (expr, type, noisy); > + } > + else > + inform (loc, "cannot convert %qE to %qT", orig_expr, type); > } > } > } > diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic1.C b/gcc/testsuite/g++.dg/concepts/diagnostic1.C > index 7da08db2792..c6589e2e671 100644 > --- a/gcc/testsuite/g++.dg/concepts/diagnostic1.C > +++ b/gcc/testsuite/g++.dg/concepts/diagnostic1.C > @@ -1,6 +1,7 @@ > // PR c++/67159 > // { dg-do compile { target c++17_only } } > // { dg-options "-fconcepts" } > +// { dg-additional-options "-fconcepts-diagnostics-depth=2" } > > template <class T, class U> > concept bool SameAs = __is_same_as(T, U); > diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic5.C b/gcc/testsuite/g++.dg/concepts/diagnostic5.C > index 2641dc18423..0d890d6f548 100644 > --- a/gcc/testsuite/g++.dg/concepts/diagnostic5.C > +++ b/gcc/testsuite/g++.dg/concepts/diagnostic5.C > @@ -4,8 +4,7 @@ > template<typename T> > concept c1 = requires { typename T::blah; }; > // { dg-message "satisfaction of .c1<T>. .with T = char." "" { target *-*-* } .-1 } > -// { dg-message "satisfaction of .c1<char\\*>." "" { target *-*-* } .-2 } > -// { dg-message ".typename T::blah. is invalid" "" { target *-*-* } .-3 } > +// { dg-message ".typename T::blah. is invalid" "" { target *-*-* } .-2 } > > template<typename T> > concept c2 = requires (T x) { *x; }; > @@ -27,8 +26,6 @@ template<typename T> > concept c5 = requires (T x) { { &x } -> c1; }; > // { dg-message "satisfaction of .c5<T>. .with T = char." "" { target *-*-* } .-1 } > // { dg-message "in requirements with .char x." "" { target *-*-* } .-2 } > -// { dg-message "does not satisfy return-type-requirement" "" { target *-*-* } .-3 } > -// { dg-error "deduced expression type does not satisfy" "" { target *-*-* } .-4 } > > template<typename T> > requires (c1<T> || c2<T>) || (c3<T> || c4<T>) || c5<T> // { dg-message "49: no operand" } > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C > index 4d521c30748..4e2d13f8eb3 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C > @@ -1,5 +1,6 @@ > // PR c++/67240 > // { dg-do compile { target c++2a } } > +// { dg-additional-options "-fconcepts-diagnostics-depth=2" } > > template <class T, class U> concept Same = __is_same_as(T,U); > > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C > index 133d29e45a4..2f912b13d6a 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C > @@ -1,5 +1,5 @@ > // { dg-do compile { target c++2a } } > -// { dg-additional-options -fconcepts-ts } > +// { dg-additional-options "-fconcepts-ts -fconcepts-diagnostics-depth=2" } > > // Test conversion requirements (not in C++20) > >
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index c5e3d64daa6..2ad82937c7e 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -3282,20 +3282,38 @@ diagnose_compound_requirement (tree req, tree args, tree in_decl) if (!type_deducible_p (expr, type, placeholder, args, quiet)) { tree orig_expr = TREE_OPERAND (req, 0); - inform (loc, "%qE does not satisfy return-type-requirement", - orig_expr); - - /* Further explain the reason for the error. */ - type_deducible_p (expr, type, placeholder, args, noisy); + if (current_constraint_diagnosis_depth + < concepts_diagnostics_max_depth) + { + inform (loc, + "%qE does not satisfy return-type-requirement, " + "because", orig_expr); + /* Further explain the reason for the error. */ + type_deducible_p (expr, type, placeholder, args, noisy); + } + else + { + inform (loc, "%qE does not satisfy return-type-requirement", + orig_expr); + concepts_diagnostics_max_depth_exceeded_p = true; + } } } else if (!expression_convertible_p (expr, type, quiet)) { tree orig_expr = TREE_OPERAND (req, 0); - inform (loc, "cannot convert %qE to %qT", orig_expr, type); - - /* Further explain the reason for the error. */ - expression_convertible_p (expr, type, noisy); + if (current_constraint_diagnosis_depth + < concepts_diagnostics_max_depth) + { + inform (loc, "cannot convert %qE to %qT because", orig_expr, type); + /* Further explain the reason for the error. */ + expression_convertible_p (expr, type, noisy); + } + else + { + inform (loc, "cannot convert %qE to %qT", orig_expr, type); + concepts_diagnostics_max_depth_exceeded_p = true; + } } } } diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic1.C b/gcc/testsuite/g++.dg/concepts/diagnostic1.C index 7da08db2792..c6589e2e671 100644 --- a/gcc/testsuite/g++.dg/concepts/diagnostic1.C +++ b/gcc/testsuite/g++.dg/concepts/diagnostic1.C @@ -1,6 +1,7 @@ // PR c++/67159 // { dg-do compile { target c++17_only } } // { dg-options "-fconcepts" } +// { dg-additional-options "-fconcepts-diagnostics-depth=2" } template <class T, class U> concept bool SameAs = __is_same_as(T, U); diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic5.C b/gcc/testsuite/g++.dg/concepts/diagnostic5.C index 3c3b42f566c..734c7fb87a6 100644 --- a/gcc/testsuite/g++.dg/concepts/diagnostic5.C +++ b/gcc/testsuite/g++.dg/concepts/diagnostic5.C @@ -4,8 +4,7 @@ template<typename T> concept c1 = requires { typename T::blah; }; // { dg-message "satisfaction of .c1<char>." "" { target *-*-* } .-1 } -// { dg-message "satisfaction of .c1<char\\*>." "" { target *-*-* } .-2 } -// { dg-message ".typename T::blah. is invalid" "" { target *-*-* } .-3 } +// { dg-message ".typename T::blah. is invalid" "" { target *-*-* } .-2 } template<typename T> concept c2 = requires (T x) { *x; }; @@ -27,8 +26,6 @@ template<typename T> concept c5 = requires (T x) { { &x } -> c1; }; // { dg-message "satisfaction of .c5<char>." "" { target *-*-* } .-1 } // { dg-message "in requirements with .char x." "" { target *-*-* } .-2 } -// { dg-message "does not satisfy return-type-requirement" "" { target *-*-* } .-3 } -// { dg-error "deduced expression type does not satisfy" "" { target *-*-* } .-4 } template<typename T> requires (c1<T> || c2<T>) || (c3<T> || c4<T>) || c5<T> // { dg-message "49: no operand" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C index 4d521c30748..4e2d13f8eb3 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C @@ -1,5 +1,6 @@ // PR c++/67240 // { dg-do compile { target c++2a } } +// { dg-additional-options "-fconcepts-diagnostics-depth=2" } template <class T, class U> concept Same = __is_same_as(T,U); diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C index 133d29e45a4..2f912b13d6a 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++2a } } -// { dg-additional-options -fconcepts-ts } +// { dg-additional-options "-fconcepts-ts -fconcepts-diagnostics-depth=2" } // Test conversion requirements (not in C++20)