From 051342116322b25db0ef6c38838a76c7a0c1231a Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
Date: Mon, 19 Jan 2009 17:50:43 -0500
Subject: [PATCH] re PR c++/23287 (Explicitly invoking destructor of template
 class in a template and is dependent)

        PR c++/23287
        * parser.c (cp_parser_unqualified_id): In a template,
        accept ~identifier.
        * typeck.c (lookup_destructor): Handle IDENTIFIER_NODE.

From-SVN: r143502
---
 gcc/cp/ChangeLog                      |  7 +++++++
 gcc/cp/parser.c                       | 10 ++++++++++
 gcc/cp/typeck.c                       | 20 +++++++++++++++++---
 gcc/testsuite/ChangeLog               |  5 +++++
 gcc/testsuite/g++.dg/template/dtor5.C | 21 +++++++++++++++++++++
 5 files changed, 60 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/dtor5.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a58d4ac27d50..5808ee5f7d88 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2009-01-19  Jason Merrill  <jason@redhat.com>
+
+	PR c++/23287
+	* parser.c (cp_parser_unqualified_id): In a template,
+	accept ~identifier.
+	* typeck.c (lookup_destructor): Handle IDENTIFIER_NODE.
+
 2009-01-16  Jason Merrill  <jason@redhat.com>
 
 	PR c++/38877
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 526a9a3acefb..5baf5f55196f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3880,6 +3880,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	    parser->scope = NULL_TREE;
 	    parser->object_scope = NULL_TREE;
 	    parser->qualifying_scope = NULL_TREE;
+	    if (processing_template_decl)
+	      cp_parser_parse_tentatively (parser);
 	    type_decl
 	      = cp_parser_class_name (parser,
 				      /*typename_keyword_p=*/false,
@@ -3888,6 +3890,14 @@ cp_parser_unqualified_id (cp_parser* parser,
 				      /*check_dependency=*/false,
 				      /*class_head_p=*/false,
 				      declarator_p);
+	    if (processing_template_decl
+		&& ! cp_parser_parse_definitely (parser))
+	      {
+		/* We couldn't find a type with this name, so just accept
+		   it and check for a match at instantiation time.  */
+		type_decl = cp_parser_identifier (parser);
+		return build_nt (BIT_NOT_EXPR, type_decl);
+	      }
 	  }
 	/* If an error occurred, assume that the name of the
 	   destructor is the same as the name of the qualifying
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 415b8a26291f..6c69256aa399 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2101,8 +2101,8 @@ build_class_member_access_expr (tree object, tree member,
   return result;
 }
 
-/* Return the destructor denoted by OBJECT.SCOPE::~DTOR_NAME, or, if
-   SCOPE is NULL, by OBJECT.~DTOR_NAME.  */
+/* Return the destructor denoted by OBJECT.SCOPE::DTOR_NAME, or, if
+   SCOPE is NULL, by OBJECT.DTOR_NAME, where DTOR_NAME is ~type.  */
 
 static tree
 lookup_destructor (tree object, tree scope, tree dtor_name)
@@ -2117,7 +2117,21 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
 	     scope, dtor_type);
       return error_mark_node;
     }
-  if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type)))
+  if (TREE_CODE (dtor_type) == IDENTIFIER_NODE)
+    {
+      /* In a template, names we can't find a match for are still accepted
+	 destructor names, and we check them here.  */
+      if (check_dtor_name (object_type, dtor_type))
+	dtor_type = object_type;
+      else
+	{
+	  error ("object type %qT does not match destructor name ~%qT",
+		 object_type, dtor_type);
+	  return error_mark_node;
+	}
+      
+    }
+  else if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type)))
     {
       error ("the type being destroyed is %qT, but the destructor refers to %qT",
 	     TYPE_MAIN_VARIANT (object_type), dtor_type);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bbe897580dde..e9bfcd25dea8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-01-19  Jason Merrill  <jason@redhat.com>
+
+	PR c++/23287
+	* g++.dg/template/dtor5.C: New test.
+
 2009-01-19  Mikael Morin  <mikael.morin@tele2.fr>
 
 	PR fortran/38859
diff --git a/gcc/testsuite/g++.dg/template/dtor5.C b/gcc/testsuite/g++.dg/template/dtor5.C
new file mode 100644
index 000000000000..8fa4eeb6f069
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dtor5.C
@@ -0,0 +1,21 @@
+// PR c++/23287
+
+template <class T> struct A
+{
+  int i;
+  ~A();
+}; 
+
+template <class T> void f(A<T> *ap) {
+  ap->~A(); 
+} 
+
+template <class T> void g(A<T> *ap) {
+  ap->~B(); 			// { dg-error "destructor name" }
+} 
+
+int main()
+{
+  f(new A<int>);
+  g(new A<int>);
+}
-- 
GitLab