On Sat, Feb 6, 2016 at 5:25 PM, Adam Butcher <a...@jessamine.co.uk> wrote: > PR c++/69139 > * cp/parser.c (cp_parser_simple_type_specifier): Don't mistake 'auto' > in trailing return function pointer types as an implicit template > parameter. > > PR c++/69139 > * g++.dg/cpp0x/trailing12.C: New test. > --- > gcc/cp/parser.c | 22 ++++++++++++++++++---- > gcc/testsuite/g++.dg/cpp0x/trailing12.C | 6 ++++++ > 2 files changed, 24 insertions(+), 4 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/trailing12.C > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index d03b0c9..c1a9674 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -16029,8 +16029,11 @@ cp_parser_simple_type_specifier (cp_parser* parser, > maybe_warn_cpp0x (CPP0X_AUTO); > if (parser->auto_is_implicit_function_template_parm_p) > { > - /* The 'auto' might be the placeholder return type for a function > decl > - with trailing return type. */ > + /* The 'auto' might be the placeholder return type for a function > type > + with trailing return type. Look for a '->' after parameter list. > + Handle pointer-to-function, function reference and > + pointer-to-member-function by tentatively consuming two pairs of > + parens before testing for '->'. */ > bool have_trailing_return_fn_decl = false; > if (cp_lexer_peek_nth_token (parser->lexer, 2)->type > == CPP_OPEN_PAREN) > @@ -16042,8 +16045,19 @@ cp_parser_simple_type_specifier (cp_parser* parser, > /*recovering*/false, > /*or_comma*/false, > > /*consume_paren*/true)) > - have_trailing_return_fn_decl > - = cp_lexer_next_token_is (parser->lexer, CPP_DEREF); > + { > + if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF)) > + have_trailing_return_fn_decl = true; > + else if ((cp_lexer_consume_token (parser->lexer)->type > + == CPP_OPEN_PAREN) > + && (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); > } > > diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing12.C > b/gcc/testsuite/g++.dg/cpp0x/trailing12.C > new file mode 100644 > index 0000000..f3e02a8 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/trailing12.C > @@ -0,0 +1,6 @@ > +// 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); > -- > 2.7.0 >
Does the trailing-return get noticed if there's an __attribute__ specifier in between it and the auto? For example, void foo (auto __attribute__ ((unused)) f (int) -> int) { } BTW, last month I posted a patch for this PR that handles all kinds of specifiers as well __attribute__ specifiers. Patch is at: https://gcc.gnu.org/ml/gcc-patches/2016-01/msg02004.html -- it makes the parser arbitrarily look ahead (while skipping over pairs of parens) until it finds a DEREF, a COMMA, a CLOSE_PAREN or an EQ. If it first finds a DEREF then have_trailing_return_fn_decl is set. Dunno if it's better to have this kind of "dumb" lookahead, or to be more explicit about one expects to consume like your followup patch does.