Message ID | 20200421180353.2777272-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: Diagnose invalid use of member function in requires | expand |
On 4/21/20 2:03 PM, Patrick Palka wrote: > This updates diagnose_valid_expression to mirror the convert_to_void check added > to tsubst_valid_expression_requirement by r10-7554. > > Passes 'make check-c++', does this look OK to commit after a full > bootstrap/regtest? OK, thanks. > gcc/cp/ChangeLog: > > PR c++/67825 > * constraint.cc (diagnose_valid_expression): Check convert_to_void here > as well as in tsubst_valid_expression_requirement. > > gcc/testsuite/ChangeLog: > > PR c++/67825 > * g++.dg/concepts/diagnostic10.C: New test. > * g++.dg/cpp2a/concepts-pr67178.C: Adjust dg-note. > --- > gcc/cp/constraint.cc | 8 ++++++-- > gcc/testsuite/g++.dg/concepts/diagnostic10.C | 18 ++++++++++++++++++ > gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C | 2 +- > 3 files changed, 25 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/concepts/diagnostic10.C > > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc > index d56ec101cd9..c05fafe5da1 100644 > --- a/gcc/cp/constraint.cc > +++ b/gcc/cp/constraint.cc > @@ -3242,7 +3242,8 @@ static tree > diagnose_valid_expression (tree expr, tree args, tree in_decl) > { > tree result = tsubst_expr (expr, args, tf_none, in_decl, false); > - if (result != error_mark_node) > + if (result != error_mark_node > + && convert_to_void (result, ICV_STATEMENT, tf_none) != error_mark_node) > return result; > > location_t loc = cp_expr_loc_or_input_loc (expr); > @@ -3250,7 +3251,10 @@ diagnose_valid_expression (tree expr, tree args, tree in_decl) > { > /* Replay the substitution error. */ > inform (loc, "the required expression %qE is invalid, because", expr); > - tsubst_expr (expr, args, tf_error, in_decl, false); > + if (result == error_mark_node) > + tsubst_expr (expr, args, tf_error, in_decl, false); > + else > + convert_to_void (result, ICV_STATEMENT, tf_error); > } > else > inform (loc, "the required expression %qE is invalid", expr); > diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic10.C b/gcc/testsuite/g++.dg/concepts/diagnostic10.C > new file mode 100644 > index 00000000000..fcc6043ca93 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/concepts/diagnostic10.C > @@ -0,0 +1,18 @@ > +// PR c++/67825 > +// { dg-do compile { target concepts } } > +// { dg-additional-options "-fconcepts-diagnostics-depth=2" } > + > +template<typename T> > + requires requires (T t) { t.f; } // { dg-error "invalid use of non-static member function" } > +void foo() { } > + > +struct S > +{ > + int f(); > +}; > + > +void > +bar() > +{ > + foo<S>(); // { dg-error "unsatisfied constraints" } > +} > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C > index ff84711a7af..7154fc2b7fe 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C > @@ -12,7 +12,7 @@ concept C0 = requires (auto x) { // { dg-error "placeholder type" } > template<typename T> > concept C1 = requires (C1 auto x) { // { dg-error "not been declared|placeholder|two or more|in requirements" } > x; // { dg-error "not declared" } > - { x } -> c; // { dg-message "not declared|does not satisfy" } > + { x } -> c; // { dg-message "is invalid" } > }; > > template<typename T> >
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index d56ec101cd9..c05fafe5da1 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -3242,7 +3242,8 @@ static tree diagnose_valid_expression (tree expr, tree args, tree in_decl) { tree result = tsubst_expr (expr, args, tf_none, in_decl, false); - if (result != error_mark_node) + if (result != error_mark_node + && convert_to_void (result, ICV_STATEMENT, tf_none) != error_mark_node) return result; location_t loc = cp_expr_loc_or_input_loc (expr); @@ -3250,7 +3251,10 @@ diagnose_valid_expression (tree expr, tree args, tree in_decl) { /* Replay the substitution error. */ inform (loc, "the required expression %qE is invalid, because", expr); - tsubst_expr (expr, args, tf_error, in_decl, false); + if (result == error_mark_node) + tsubst_expr (expr, args, tf_error, in_decl, false); + else + convert_to_void (result, ICV_STATEMENT, tf_error); } else inform (loc, "the required expression %qE is invalid", expr); diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic10.C b/gcc/testsuite/g++.dg/concepts/diagnostic10.C new file mode 100644 index 00000000000..fcc6043ca93 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/diagnostic10.C @@ -0,0 +1,18 @@ +// PR c++/67825 +// { dg-do compile { target concepts } } +// { dg-additional-options "-fconcepts-diagnostics-depth=2" } + +template<typename T> + requires requires (T t) { t.f; } // { dg-error "invalid use of non-static member function" } +void foo() { } + +struct S +{ + int f(); +}; + +void +bar() +{ + foo<S>(); // { dg-error "unsatisfied constraints" } +} diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C index ff84711a7af..7154fc2b7fe 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C @@ -12,7 +12,7 @@ concept C0 = requires (auto x) { // { dg-error "placeholder type" } template<typename T> concept C1 = requires (C1 auto x) { // { dg-error "not been declared|placeholder|two or more|in requirements" } x; // { dg-error "not declared" } - { x } -> c; // { dg-message "not declared|does not satisfy" } + { x } -> c; // { dg-message "is invalid" } }; template<typename T>