diff mbox

PR c++/69139

Message ID 1454797548-5422-1-git-send-email-adam@jessamine.co.uk
State New
Headers show

Commit Message

Adam Butcher Feb. 6, 2016, 10:25 p.m. UTC
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

Comments

Jason Merrill Feb. 8, 2016, 3:40 p.m. UTC | #1
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
Patrick Palka Feb. 8, 2016, 4:43 p.m. UTC | #2
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.
Jason Merrill Feb. 8, 2016, 6:38 p.m. UTC | #3
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 mbox

Patch

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);