On Tue, Jan 26, 2016 at 11:31 AM, Patrick Palka <patr...@parcs.ath.cx> wrote: > This patch makes the parser more robust in determining whether an 'auto' > specifier that appears in a parameter declaration corresponds to a > placeholder for a late return type, or corresponds to an implicit > template parameter as for an abbreviated function template. > > Bootstrap + regtest in progress on x86_64-pc-linux-gnu, will also test > this change against Boost. OK to commit if testing succeeds? What > about for GCC 4.9/5? > > gcc/cp/ChangeLog: > > PR c++/69139 > * parser.c (cp_parser_simple_type_specifier): Make the check > for disambiguating between an 'auto' placeholder and an implicit > template parameter more robust. > > gcc/testsuite/ChangeLog: > > PR c++/69139 > * g++.dg/cpp0x/auto47.C: New test. > --- > gcc/cp/parser.c | 33 +++++++++++++++++++++++---------- > gcc/testsuite/g++.dg/cpp0x/auto47.C | 20 ++++++++++++++++++++ > 2 files changed, 43 insertions(+), 10 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/auto47.C > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index d03b0c9..56c834f 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -16032,20 +16032,33 @@ cp_parser_simple_type_specifier (cp_parser* parser, > /* The 'auto' might be the placeholder return type for a function > decl > with trailing return type. */ > bool have_trailing_return_fn_decl = false; > - if (cp_lexer_peek_nth_token (parser->lexer, 2)->type > - == CPP_OPEN_PAREN) > + > + cp_parser_parse_tentatively (parser); > + cp_lexer_consume_token (parser->lexer); > + while (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ) > + && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA) > + && cp_lexer_next_token_is_not (parser->lexer, > CPP_CLOSE_PAREN) > + && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF)) > { > - cp_parser_parse_tentatively (parser); > - cp_lexer_consume_token (parser->lexer); > - cp_lexer_consume_token (parser->lexer); > - if (cp_parser_skip_to_closing_parenthesis (parser, > + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) > + { > + cp_lexer_consume_token (parser->lexer); > + cp_parser_skip_to_closing_parenthesis (parser, > /*recovering*/false, > /*or_comma*/false, > - > /*consume_paren*/true)) > - have_trailing_return_fn_decl > - = cp_lexer_next_token_is (parser->lexer, CPP_DEREF); > - cp_parser_abort_tentative_parse (parser); > + > /*consume_paren*/true); > + continue; > + } > + > + if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF)) > + { > + have_trailing_return_fn_decl = true; > + break; > + } > + > + cp_lexer_consume_token (parser->lexer); > } > + cp_parser_abort_tentative_parse (parser); > > if (have_trailing_return_fn_decl) > { > diff --git a/gcc/testsuite/g++.dg/cpp0x/auto47.C > b/gcc/testsuite/g++.dg/cpp0x/auto47.C > new file mode 100644 > index 0000000..08adf31 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/auto47.C > @@ -0,0 +1,20 @@ > +// PR c++/69139 > +// { dg-do compile { target c++11 } } > + > +auto get(int) -> int { return {}; } > +template <class R> int f(auto (*)(int) -> R) { return {}; } > +int i = f(get); > + > +int foo1 (auto (int) -> char); > + > +int foo2 (auto f(int) -> char); > + > +int foo2 (auto (f)(int) -> char); > + > +int foo3 (auto (*f)(int) -> char); > + > +int foo4 (auto (*const **&f)(int) -> char); > + > +int foo5 (auto (*const **&f)(int, int *) -> char); > + > +int foo6 (auto (int) const -> char); // { dg-error "const" } > -- > 2.7.0.134.gf5046bd.dirty >
Ping.