diff options
author | Patrick Palka <ppalka@gcc.gnu.org> | 2016-02-08 23:06:21 +0000 |
---|---|---|
committer | Patrick Palka <ppalka@gcc.gnu.org> | 2016-02-08 23:06:21 +0000 |
commit | efb45a9f4ae816d61fd06fedeb86a50d7434d157 (patch) | |
tree | 98b18911a7e3fb68c913c06d673f62253a06e20e | |
parent | 20a0c6f9bdbd781ed5d413a10a06764a174dc394 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/parser.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/trailing12.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/trailing13.C | 12 |
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; |