Fix PR c++/69139 (deduction failure with trailing return type)
authorppalka <ppalka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Feb 2016 23:06:21 +0000 (23:06 +0000)
committerppalka <ppalka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Feb 2016 23:06:21 +0000 (23:06 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233231 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/trailing12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/trailing13.C [new file with mode: 0644]

index 0fc4047..8ed7828 100644 (file)
@@ -1,5 +1,12 @@
 2016-02-08  Patrick Palka  <ppalka@gcc.gnu.org>
 
+       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.
+
+2016-02-08  Patrick Palka  <ppalka@gcc.gnu.org>
+
        PR c++/69283
        PR c++/67835
        * decl2.c (mark_used): When given a TEMPLATE_DECL, return after
index b7bfa77..6f47edf 100644 (file)
@@ -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)
            {
index 4af81dd..700ba0e 100644 (file)
@@ -1,5 +1,11 @@
 2016-02-08  Patrick Palka  <ppalka@gcc.gnu.org>
 
+       PR c++/69139
+       * g++.dg/cpp0x/trailing12.C: New test.
+       * g++.dg/cpp0x/trailing13.C: New test.
+
+2016-02-08  Patrick Palka  <ppalka@gcc.gnu.org>
+
        PR c++/69283
        PR c++/67835
        * g++.dg/cpp1y/auto-fn29.C: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing12.C b/gcc/testsuite/g++.dg/cpp0x/trailing12.C
new file mode 100644 (file)
index 0000000..a27d988
--- /dev/null
@@ -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 (file)
index 0000000..2681bcd
--- /dev/null
@@ -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;