aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@gcc.gnu.org>2016-02-08 23:06:21 +0000
committerPatrick Palka <ppalka@gcc.gnu.org>2016-02-08 23:06:21 +0000
commitefb45a9f4ae816d61fd06fedeb86a50d7434d157 (patch)
tree98b18911a7e3fb68c913c06d673f62253a06e20e
parent20a0c6f9bdbd781ed5d413a10a06764a174dc394 (diff)
downloadgcc-efb45a9f4ae816d61fd06fedeb86a50d7434d157.zip
gcc-efb45a9f4ae816d61fd06fedeb86a50d7434d157.tar.gz
gcc-efb45a9f4ae816d61fd06fedeb86a50d7434d157.tar.bz2
Fix PR c++/69139 (deduction failure with trailing return type)
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. From-SVN: r233231
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/parser.c33
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing12.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing13.C12
5 files changed, 70 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0fc4047..8ed7828 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b7bfa77..6f47edf 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/ChangeLog b/gcc/testsuite/ChangeLog
index 4af81dd..700ba0e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
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;