diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e371a408c488d1d2bfc7efd09bbe974bf4e63ef6..7051a42831f537636b5dfd37fd49a1ba817cded2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2019-12-11 Jason Merrill <jason@redhat.com> + PR c++/92105 - decltype(decltype) error cascade. + * parser.c (cp_parser_decltype_expr): Don't tentative_firewall here. + (cp_parser_decltype): Do it here. Remember a non-tentative error. + PR c++/57082 - new X{} and private destructor. * init.c (build_new_1): Also pass tf_no_cleanup to build_special_member_call. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bf6d291ba9d9354134df8d84cb89c433413d705d..16d1359c47df92c409c1f7077e30b1f1e024506b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -14637,11 +14637,6 @@ cp_parser_decltype_expr (cp_parser *parser, cp_token *id_expr_start_token; tree expr; - /* Since we're going to preserve any side-effects from this parse, set up a - firewall to protect our callers from cp_parser_commit_to_tentative_parse - in the expression. */ - tentative_firewall firewall (parser); - /* First, try parsing an id-expression. */ id_expr_start_token = cp_lexer_peek_token (parser->lexer); cp_parser_parse_tentatively (parser); @@ -14733,9 +14728,6 @@ cp_parser_decltype_expr (cp_parser *parser, expression. */ cp_parser_abort_tentative_parse (parser); - /* Commit to the tentative_firewall so we get syntax errors. */ - cp_parser_commit_to_tentative_parse (parser); - /* Parse a full expression. */ expr = cp_parser_expression (parser, /*pidk=*/NULL, /*cast_p=*/false, /*decltype_p=*/true); @@ -14773,6 +14765,17 @@ cp_parser_decltype (cp_parser *parser) if (!parens.require_open (parser)) return error_mark_node; + /* Since we're going to preserve any side-effects from this parse, set up a + firewall to protect our callers from cp_parser_commit_to_tentative_parse + in the expression. */ + tentative_firewall firewall (parser); + + /* If in_declarator_p, a reparse as an expression might succeed (60361). + Otherwise, commit now for better diagnostics. */ + if (cp_parser_uncommitted_to_tentative_parse_p (parser) + && !parser->in_declarator_p) + cp_parser_commit_to_topmost_tentative_parse (parser); + push_deferring_access_checks (dk_deferred); tree expr = NULL_TREE; @@ -14833,10 +14836,16 @@ cp_parser_decltype (cp_parser *parser) } /* Parse to the closing `)'. */ - if (!parens.require_close (parser)) + if (expr == error_mark_node || !parens.require_close (parser)) { cp_parser_skip_to_closing_parenthesis (parser, true, false, /*consume_paren=*/true); + expr = error_mark_node; + } + + /* If we got a parse error while tentative, bail out now. */ + if (cp_parser_error_occurred (parser)) + { pop_deferring_access_checks (); return error_mark_node; } @@ -14859,6 +14868,11 @@ cp_parser_decltype (cp_parser *parser) start_token->u.tree_check_value->value = expr; start_token->u.tree_check_value->checks = get_deferred_access_checks (); start_token->keyword = RID_MAX; + + location_t loc = start_token->location; + loc = make_location (loc, loc, parser->lexer); + start_token->location = loc; + cp_lexer_purge_tokens_after (parser->lexer, start_token); pop_to_parent_deferring_access_checks (); diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-err1.C b/gcc/testsuite/g++.dg/cpp0x/decltype-err1.C new file mode 100644 index 0000000000000000000000000000000000000000..302cb64aafc76e36158bad72f8d120151c6b823f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-err1.C @@ -0,0 +1,7 @@ +// PR c++/92105 +// { dg-do compile { target c++11 } } + +// Test that we get exactly one "expected" error. + +decltype(decltype) x = 42; // { dg-bogus "expected.*expected" } +// { dg-error "expected" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype10.C b/gcc/testsuite/g++.dg/cpp0x/decltype10.C index 846d0bf57cf2aac18f4d3145e6d4121a38d731ee..fe7247269f5d9aac1ae7a2e2a0083c60c224701b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype10.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype10.C @@ -6,4 +6,4 @@ template<int> struct A static int i; }; -template<int N> int A<N>::i(decltype (A::i; // { dg-error "expected primary-expression before" } +template<int N> int A<N>::i(decltype (A::i; // { dg-error "expected" }