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" }