Message ID | 1454797548-5422-1-git-send-email-adam@jessamine.co.uk |
---|---|
State | New |
Headers | show |
On 02/06/2016 05:25 PM, Adam Butcher wrote: > + 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); Let's reorganize this so you only check CPP_DEREF in one place; this is more important now that you've added more processing to only one of them in your followup patch. Jason
On Sat, Feb 6, 2016 at 5:25 PM, Adam Butcher <adam@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.
On 02/08/2016 11:43 AM, Patrick Palka wrote: > 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. Hmm, I think I prefer your approach, but please add the testcase with stuff between ) and ->. Jason
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);