diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 94de8b7afaaaa5a45af5ceaf1ded81b73987203b..8f767b06cd9d5696ad4f0d567e9edf48aa883a33 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,12 @@
 2006-08-17  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
+	PR c++/28606
+	* parser.c (cp_parser_diagnose_invalid_type_name): Handle BIT_NOT_EXPR.
+	Fix formatting.
+	(cp_parser_parse_and_diagnose_invalid_type_name): Tighten condition
+	for valid type-names.
+	(cp_parser_unqualified_id): Fix error handling for destructors.
+
 	PR c++/28710
 	* decl.c (xref_tag): Improve error message.  Return early on error.
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7bfa86665b75bb126427e0d35d2c62e3fc648d2d..78e6eb69d55992aaac667a21e4c61e4101e5bdf4 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2093,8 +2093,9 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
   if (TREE_CODE (decl) == TEMPLATE_DECL)
-    error ("invalid use of template-name %qE without an argument list",
-      decl);
+    error ("invalid use of template-name %qE without an argument list", decl);
+  else if (TREE_CODE (id) == BIT_NOT_EXPR)
+    error ("invalid use of destructor %qD as a type", id);
   else if (!parser->scope)
     {
       /* Issue an error message.  */
@@ -2187,8 +2188,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
       cp_parser_abort_tentative_parse (parser);
       return false;
     }
-  if (!cp_parser_parse_definitely (parser)
-      || TREE_CODE (id) != IDENTIFIER_NODE)
+  if (!cp_parser_parse_definitely (parser) || TREE_CODE (id) == TYPE_DECL)
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
@@ -3407,14 +3407,17 @@ cp_parser_unqualified_id (cp_parser* parser,
 	/* Check for invalid scopes.  */
 	if (scope == error_mark_node)
 	  {
-	    cp_parser_skip_to_end_of_statement (parser);
+	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+	      cp_lexer_consume_token (parser->lexer);
 	    return error_mark_node;
 	  }
 	if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
 	      error ("scope %qT before %<~%> is not a class-name", scope);
-	    cp_parser_skip_to_end_of_statement (parser);
+	    cp_parser_simulate_error (parser);
+	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+	      cp_lexer_consume_token (parser->lexer);
 	    return error_mark_node;
 	  }
 	gcc_assert (!scope || TYPE_P (scope));
@@ -3514,6 +3517,7 @@ cp_parser_unqualified_id (cp_parser* parser,
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
 	      error ("declaration of %<~%T%> as member of %qT",
 		     type_decl, scope);
+	    cp_parser_simulate_error (parser);
 	    return error_mark_node;
 	  }
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9f3eb37b034b27b40e815df9f1fa378d49864de7..3ccd52def7b924e46f84aa3e6236e90c8704ca95 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-08-17  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
+
+	PR c++/28606
+	* g++.dg/parse/dtor11.C: New test.
+
 2006-08-17  Maxim Kuvyrkov  <mkuvyrkov@ispras.ru>
 
 	PR rtl-optimization/28489
diff --git a/gcc/testsuite/g++.dg/parse/dtor11.C b/gcc/testsuite/g++.dg/parse/dtor11.C
new file mode 100644
index 0000000000000000000000000000000000000000..63ffb60bac107dfe2f8f5d9d138ac4d91de01592
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/dtor11.C
@@ -0,0 +1,12 @@
+// PR c++/28606
+// { dg-do compile }
+
+struct A
+{
+  ~A A();     // { dg-error "destructor" }
+};
+
+struct B
+{
+  A::~B B();  // { dg-error "as member of" }
+};