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.

Reply via email to