On Sat, Feb 6, 2016 at 5:25 PM, Adam Butcher <[email protected]> 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.