On Wed, 25 Mar 2020, Marek Polacek wrote: > On Wed, Mar 25, 2020 at 12:17:41PM -0400, Patrick Palka via Gcc-patches wrote: > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > > index 03ecd7838f6..14a22b85318 100644 > > --- a/gcc/cp/parser.c > > +++ b/gcc/cp/parser.c > > @@ -27689,7 +27689,12 @@ cp_parser_requires_expression (cp_parser *parser) > > else > > parms = NULL_TREE; > > > > - /* Parse the requirement body. */ > > + /* Always parse the requirement body as if we're inside a template so > > that > > + we always do full semantic processing only during evaluation of this > > + requires-expression and not also now during parsing. */ > > + processing_template_decl_sentinel ptds; > > This looks weird; this sentinel will always set processing_template_decl to 0, > right? So... > > > + if (!processing_template_decl) > > + processing_template_decl = 1; > > ...this will always be true? Did you mean to use temp_override instead?
Oops, good point. The intention was to set processing_template_decl to 1 when it is 0, and to otherwise not change it. So it looks like I should pass false to processing_template_decl_sentinel's ctor here, like so. > > I don't dare to say if this approach is OK or not, but I've certainly had > my share of fun with CALL_EXPRs in templates :). Hehe :) -- >8 -- gcc/cp/ChangeLog: PR c++/94252 * parser.c (cp_parser_requires_expression): Always parse the requirement body as if we're processing a template, by temporarily setting processing_template_decl to non-zero. * semantics.c (finish_static_assert): Also explain an assertion failure when the condition is a REQUIRES_EXPR. gcc/testsuite/ChangeLog: PR c++/94252 * g++.dg/concepts/diagnostic7.C: New test. * g++.dg/concepts/pr94252.C: New test. --- gcc/cp/parser.c | 7 ++++++- gcc/cp/semantics.c | 6 ++++-- gcc/testsuite/g++.dg/concepts/diagnostic7.C | 12 ++++++++++++ gcc/testsuite/g++.dg/concepts/pr94252.C | 14 ++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/concepts/diagnostic7.C create mode 100644 gcc/testsuite/g++.dg/concepts/pr94252.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 03ecd7838f6..6150814ea9e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -27689,7 +27689,12 @@ cp_parser_requires_expression (cp_parser *parser) else parms = NULL_TREE; - /* Parse the requirement body. */ + /* Always parse the requirement body as if we're inside a template so that + we always do full semantic processing only during evaluation of this + requires-expression and not also now during parsing. */ + processing_template_decl_sentinel ptds (false); + if (!processing_template_decl) + processing_template_decl = 1; reqs = cp_parser_requirement_body (parser); if (reqs == error_mark_node) return error_mark_node; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index bcb2e72fbb5..e998b373af4 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -9691,8 +9691,10 @@ finish_static_assert (tree condition, tree message, location_t location, error ("static assertion failed: %s", TREE_STRING_POINTER (message)); - /* Actually explain the failure if this is a concept check. */ - if (concept_check_p (orig_condition)) + /* Actually explain the failure if this is a concept check or a + requires-expression. */ + if (concept_check_p (orig_condition) + || TREE_CODE (orig_condition) == REQUIRES_EXPR) diagnose_constraints (location, orig_condition, NULL_TREE); } else if (condition && condition != error_mark_node) diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic7.C b/gcc/testsuite/g++.dg/concepts/diagnostic7.C new file mode 100644 index 00000000000..f78e9bb8240 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/diagnostic7.C @@ -0,0 +1,12 @@ +// { dg-do compile { target c++2a } } + +template<typename A, typename B> + concept same_as = __is_same(A, B); // { dg-message ".void. is not the same as .int." } + +void f(); + +static_assert(requires { { f() } noexcept -> same_as<int>; }); +// { dg-error "static assertion failed" "" { target *-*-* } .-1 } +// { dg-message "not .noexcept." "" { target *-*-* } .-2 } +// { dg-message "return-type-requirement" "" { target *-*-* } .-3 } +// { dg-error "does not satisfy placeholder constraints" "" { target *-*-* } .-4 } diff --git a/gcc/testsuite/g++.dg/concepts/pr94252.C b/gcc/testsuite/g++.dg/concepts/pr94252.C new file mode 100644 index 00000000000..7b93997363a --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr94252.C @@ -0,0 +1,14 @@ +// PR c++/94252 +// { dg-do compile { target c++2a } } + +auto f = []{ return 0; }; +static_assert(requires { f(); }); + +template<typename A, typename B> + concept same_as = __is_same(A, B); + +struct S { int f(int) noexcept; }; +static_assert(requires(S o, int i) { + o.f(i); + { o.f(i) } noexcept -> same_as<int>; +}); -- 2.26.0.rc1.11.g30e9940356