diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 00ac24e269372c1aa51d59d65e4a5eeeed906333..ecc83b43a3152a8d18d6411c210f7111ec494335 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2009-02-20  Jason Merrill  <jason@redhat.com>
+
+	PR c++/39225
+	* decl.c (grokdeclarator): Handle ~identifier.
+
 2009-02-19  Jakub Jelinek  <jakub@redhat.com>
 
 	PR target/39175
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 930f944e8a11364a4f5ef8b9e4068d35acca9093..551764dc29cc077a7a40f05338a39b5034daf42a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7659,7 +7659,9 @@ grokdeclarator (const cp_declarator *declarator,
 		    }
 
 		  type = TREE_OPERAND (decl, 0);
-		  name = IDENTIFIER_POINTER (constructor_name (type));
+		  if (TYPE_P (type))
+		    type = constructor_name (type);
+		  name = IDENTIFIER_POINTER (type);
 		  dname = decl;
 		}
 		break;
@@ -8161,8 +8163,9 @@ grokdeclarator (const cp_declarator *declarator,
       switch (TREE_CODE (unqualified_id))
 	{
 	case BIT_NOT_EXPR:
-	  unqualified_id
-	    = constructor_name (TREE_OPERAND (unqualified_id, 0));
+	  unqualified_id = TREE_OPERAND (unqualified_id, 0);
+	  if (TYPE_P (unqualified_id))
+	    unqualified_id = constructor_name (unqualified_id);
 	  break;
 
 	case IDENTIFIER_NODE:
@@ -9038,21 +9041,20 @@ grokdeclarator (const cp_declarator *declarator,
 	    /* Check that the name used for a destructor makes sense.  */
 	    if (sfk == sfk_destructor)
 	      {
+		tree uqname = id_declarator->u.id.unqualified_name;
+
 		if (!ctype)
 		  {
 		    gcc_assert (friendp);
 		    error ("expected qualified name in friend declaration "
-			   "for destructor %qD",
-			   id_declarator->u.id.unqualified_name);
+			   "for destructor %qD", uqname);
 		    return error_mark_node;
 		  }
 
-		if (!same_type_p (TREE_OPERAND
-				  (id_declarator->u.id.unqualified_name, 0),
-				  ctype))
+		if (!check_dtor_name (ctype, TREE_OPERAND (uqname, 0)))
 		  {
 		    error ("declaration of %qD as member of %qT",
-			   id_declarator->u.id.unqualified_name, ctype);
+			   uqname, ctype);
 		    return error_mark_node;
 		  }
 	      }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7a5f58e0e7bdace0e8c594f711af6e113a65eec7..e84cac93ff5352cf2ebc30f41c1809774fc30359 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-02-20  Jason Merrill  <jason@redhat.com>
+
+	PR c++/39225
+	* g++.dg/parse/dtor15.C: New test.
+
 2009-02-19  Kazu Hirata  <kazu@codesourcery.com>
 
 	* gcc.c-torture/execute/20090219-1.c: New.
@@ -68,6 +73,9 @@
 
 2009-02-18  Jason Merrill  <jason@redhat.com>
 
+	PR c++/38880
+	* g++.dg/init/const7.C: Remove XFAIL.
+
 	PR target/39179
 	* g++.dg/opt/const6.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/parse/dtor15.C b/gcc/testsuite/g++.dg/parse/dtor15.C
new file mode 100644
index 0000000000000000000000000000000000000000..ae85a702a408a288ee99f57fbce7787e9defe233
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/dtor15.C
@@ -0,0 +1,16 @@
+// PR c++/39225
+
+template <class T>
+class A
+{
+public:
+    A() {}
+    ~B() {}			// { dg-error "~B" }
+};
+
+int main()
+{
+    A<int> *a = new A<int>;
+
+    return 0;
+}