[PATCH] c++: Diagnose when "requires" is used instead of "requires requires" [PR94306]

Patrick Palka ppalka@redhat.com
Thu Mar 26 22:36:08 GMT 2020


On Thu, 26 Mar 2020, Jason Merrill wrote:

> On 3/26/20 5:28 PM, Patrick Palka wrote:
> > This adds support to detect and recover from the case where an opening brace
> > immediately follows the start of a requires-clause.  So rather than emitting
> > the
> > error
> > 
> >    error: expected primary-expression before '{' token
> > 
> > followed by a slew of irrevelant errors, we now assume the user had intended
> > to
> > write "requires requires {" and diagnose and recover accordingly.
> > 
> > Tested on x86_64-pc-linux-gnu, does this look OK?
> > 
> > gcc/cp/ChangeLog:
> > 
> > 	PR c++/94306
> > 	* parser.c (cp_parser_requires_clause_opt): Diagnose and recover from
> > 	"requires {" when "requires requires {" was probably intended.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > 	PR c++/94306
> > 	* g++.dg/concepts/diagnostic8.C: New test.
> > ---
> >   gcc/cp/parser.c                             | 17 ++++++++++++++++-
> >   gcc/testsuite/g++.dg/concepts/diagnostic8.C |  6 ++++++
> >   2 files changed, 22 insertions(+), 1 deletion(-)
> >   create mode 100644 gcc/testsuite/g++.dg/concepts/diagnostic8.C
> > 
> > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> > index 05363653691..73c2c2cb010 100644
> > --- a/gcc/cp/parser.c
> > +++ b/gcc/cp/parser.c
> > @@ -27639,7 +27639,22 @@ cp_parser_requires_clause_opt (cp_parser *parser,
> > bool lambda_p)
> >   	}
> >         return NULL_TREE;
> >       }
> > -  cp_lexer_consume_token (parser->lexer);
> > +
> > +  cp_token *tok2 = cp_lexer_peek_nth_token (parser->lexer, 2);
> > +  if (tok2->type == CPP_OPEN_BRACE)
> 
> Do we want to handle an open paren the same way?

Hmm, wouldn't the error recovery be significantly different for an open
paren here?  Just pretending that there's another "requires" token would
mean we proceed as if we got "requires requires (" but that is still
ill-formed I think.

> 
> > +    {
> > +      /* An opening brace following the start of a requires-clause is
> > +	 ill-formed; the user likely forgot the second `requires' that
> > +	 would start a requires-expression.  */
> > +      gcc_rich_location richloc (tok2->location);
> > +      richloc.add_fixit_insert_before (" requires");
> > +      error_at (&richloc, "missing additional %<requires%> to start "
> > +		"a requires-expression");
> > +      /* Don't consume the `requires', so that it's reused as the start of
> > a
> > +	 requires-expression.  */
> > +    }
> > +  else
> > +    cp_lexer_consume_token (parser->lexer);
> >       if (!flag_concepts_ts)
> >       return cp_parser_requires_clause_expression (parser, lambda_p);
> > diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic8.C
> > b/gcc/testsuite/g++.dg/concepts/diagnostic8.C
> > new file mode 100644
> > index 00000000000..70d7e4a9cc1
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/concepts/diagnostic8.C
> > @@ -0,0 +1,6 @@
> > +// PR c++/94306
> > +// { dg-do compile { target c++2a } }
> > +
> > +template<typename T> struct S { };
> > +template<typename T> requires { typename T::type; } struct S<T> { };
> > +// { dg-error "missing additional .requires." "" { target *-*-* } .-1 }
> > 
> 
> 



More information about the Gcc-patches mailing list