[PATCH] PR c++/69139

Patrick Palka patrick@parcs.ath.cx
Mon Feb 8 19:14:00 GMT 2016


On Mon, 8 Feb 2016, Jason Merrill wrote:

> 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 ->.

Done.  Does this look OK?

-- >8 --

gcc/cp/ChangeLog:

 	PR c++/69139
 	* parser.c (cp_parser_simple_type_specifier): Make the check
 	for disambiguating between an 'auto' placeholder and an implicit
 	template parameter more robust.

gcc/testsuite/ChangeLog:

 	PR c++/69139
 	* g++.dg/cpp0x/trailing12.C: New test.
 	* g++.dg/cpp0x/trailing13.C: New test.
---
  gcc/cp/parser.c                         | 33 +++++++++++++++++++++++----------
  gcc/testsuite/g++.dg/cpp0x/trailing12.C | 22 ++++++++++++++++++++++
  gcc/testsuite/g++.dg/cpp0x/trailing13.C | 12 ++++++++++++
  3 files changed, 57 insertions(+), 10 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/trailing12.C
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/trailing13.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d03b0c9..56c834f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16032,20 +16032,33 @@ cp_parser_simple_type_specifier (cp_parser* parser,
  	  /* The 'auto' might be the placeholder return type for a function decl
  	     with trailing return type.  */
  	  bool have_trailing_return_fn_decl = false;
-	  if (cp_lexer_peek_nth_token (parser->lexer, 2)->type
-	      == CPP_OPEN_PAREN)
+
+	  cp_parser_parse_tentatively (parser);
+	  cp_lexer_consume_token (parser->lexer);
+	  while (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
+		 && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
+		 && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+		 && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))
  	    {
-	      cp_parser_parse_tentatively (parser);
-	      cp_lexer_consume_token (parser->lexer);
-	      cp_lexer_consume_token (parser->lexer);
-	      if (cp_parser_skip_to_closing_parenthesis (parser,
+	      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+		{
+		  cp_lexer_consume_token (parser->lexer);
+		  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);
+							 /*consume_paren*/true);
+		  continue;
+		}
+
+	      if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
+		{
+		  have_trailing_return_fn_decl = true;
+		  break;
+		}
+
+	      cp_lexer_consume_token (parser->lexer);
  	    }
+	  cp_parser_abort_tentative_parse (parser);

  	  if (have_trailing_return_fn_decl)
  	    {
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing12.C b/gcc/testsuite/g++.dg/cpp0x/trailing12.C
new file mode 100644
index 0000000..a27d988
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing12.C
@@ -0,0 +1,22 @@
+// 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);
+
+int foo1 (auto (int) -> char);
+
+int foo2 (auto f(int) -> char);
+
+int foo2 (auto (f)(int) -> char);
+
+int foo3 (auto (*f)(int) -> char);
+
+int foo4 (auto (*const **&f)(int) -> char);
+
+int foo5 (auto (*const **&f)(int, int *) -> char);
+
+int foo6 (auto (int) const -> char); // { dg-error "const" }
+
+void foo7 (auto __attribute__ ((unused)) f (int) -> int) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing13.C b/gcc/testsuite/g++.dg/cpp0x/trailing13.C
new file mode 100644
index 0000000..2681bcd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing13.C
@@ -0,0 +1,12 @@
+// PR c++/69139
+// { dg-do compile { target c++11 } }
+
+struct X {
+  auto get(int) const & noexcept -> int { return {}; }
+  auto get(int) && throw () -> long { return {}; }
+};
+
+template <class R> auto f(auto (X::*)(int) const & -> R) -> R {}
+
+using I = decltype(f(&X::get));
+using I = int;
-- 
2.7.1.257.g925a48d



More information about the Gcc-patches mailing list