From eac53a7cf5f7ae50cb7d4abc91ae6705d59a296d Mon Sep 17 00:00:00 2001
From: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Sun, 17 May 2009 18:01:33 +0000
Subject: [PATCH] 	PR c++/40139 	* pt.c (tsubst_qualified_id): Retain
 the type if we aren't dealing 	with a dependent type.  Actually look up the
 destructor. 	* semantics.c (finish_id_expression): Fix logic. 
 (finish_qualified_id_expr): Don't try to use 'this' if we aren't in 	a
 function. 	* typeck.c (build_x_unary_op): Diagnose taking the address of
 a 	constructor or destructor. 	* tree.c (get_first_fn): Handle
 OFFSET_REF.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147638 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog                      | 12 ++++++++++++
 gcc/cp/pt.c                           | 25 +++++++++++++++++++------
 gcc/cp/semantics.c                    | 27 +++++++++++++--------------
 gcc/cp/tree.c                         |  3 ++-
 gcc/cp/typeck.c                       | 16 ++++++++++++++--
 gcc/testsuite/ChangeLog               |  5 +++++
 gcc/testsuite/g++.dg/template/dtor6.C | 16 ++++++++++++++++
 7 files changed, 81 insertions(+), 23 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/dtor6.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bffec90178c0..af4b69ca7183 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2009-05-16  Jason Merrill  <jason@redhat.com>
+
+	PR c++/40139
+	* pt.c (tsubst_qualified_id): Retain the type if we aren't dealing
+	with a dependent type.  Actually look up the destructor.
+	* semantics.c (finish_id_expression): Fix logic.
+	(finish_qualified_id_expr): Don't try to use 'this' if we aren't in
+	a function.
+	* typeck.c (build_x_unary_op): Diagnose taking the address of a
+	constructor or destructor.
+	* tree.c (get_first_fn): Handle OFFSET_REF.
+
 2009-05-17  Joseph Myers  <joseph@codesourcery.com>
 
 	* tree.c (cxx_printable_name_internal): Allow consecutive
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e100d6b116c7..2ca28d69c648 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9930,16 +9930,29 @@ tsubst_qualified_id (tree qualified_id, tree args,
     expr = name;
 
   if (dependent_type_p (scope))
-    return build_qualified_name (/*type=*/NULL_TREE,
-				 scope, expr,
-				 QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+    {
+      tree type = NULL_TREE;
+      if (DECL_P (expr) && !dependent_scope_p (scope))
+	type = TREE_TYPE (expr);
+      return build_qualified_name (type, scope, expr,
+				   QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+    }
 
   if (!BASELINK_P (name) && !DECL_P (expr))
     {
       if (TREE_CODE (expr) == BIT_NOT_EXPR)
-	/* If this were actually a destructor call, it would have been
-	   parsed as such by the parser.  */
-	expr = error_mark_node;
+	{
+	  /* A BIT_NOT_EXPR is used to represent a destructor.  */
+	  if (!check_dtor_name (scope, TREE_OPERAND (expr, 0)))
+	    {
+	      error ("qualifying type %qT does not match destructor name ~%qT",
+		     scope, TREE_OPERAND (expr, 0));
+	      expr = error_mark_node;
+	    }
+	  else
+	    expr = lookup_qualified_name (scope, complete_dtor_identifier,
+					  /*is_type_p=*/0, false);
+	}
       else
 	expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
       if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 8c0a1e510ce0..18aa0519e1c4 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1664,11 +1664,10 @@ finish_qualified_id_expr (tree qualifying_class,
       fns = BASELINK_FUNCTIONS (expr);
       if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
 	fns = TREE_OPERAND (fns, 0);
-      /* If so, the expression may be relative to the current
-	 class.  */
+      /* If so, the expression may be relative to 'this'.  */
       if (!shared_member_p (fns)
-	  && current_class_type
-	  && DERIVED_FROM_P (qualifying_class, current_class_type))
+	  && current_class_ref
+	  && DERIVED_FROM_P (qualifying_class, TREE_TYPE (current_class_ref)))
 	expr = (build_class_member_access_expr
 		(maybe_dummy_object (qualifying_class, NULL),
 		 expr,
@@ -2871,16 +2870,16 @@ finish_id_expression (tree id_expression,
 						     done, address_p,
 						     template_p,
 						     template_arg_p);
-		  else if (dependent_scope_p (scope))
-		    decl = build_qualified_name (/*type=*/NULL_TREE,
-						 scope,
-						 id_expression,
-						 template_p);
-		  else if (DECL_P (decl))
-		    decl = build_qualified_name (TREE_TYPE (decl),
-						 scope,
-						 id_expression,
-						 template_p);
+		  else
+		    {
+		      tree type = NULL_TREE;
+		      if (DECL_P (decl) && !dependent_scope_p (scope))
+			type = TREE_TYPE (decl);
+		      decl = build_qualified_name (type,
+						   scope,
+						   id_expression,
+						   template_p);
+		    }
 		}
 	      if (TREE_TYPE (decl))
 		decl = convert_from_reference (decl);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 219cb399f9c8..f1868f5e5d7d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1200,7 +1200,8 @@ get_first_fn (tree from)
 {
   gcc_assert (is_overloaded_fn (from));
   /* A baselink is also considered an overloaded function.  */
-  if (TREE_CODE (from) == COMPONENT_REF)
+  if (TREE_CODE (from) == OFFSET_REF
+      || TREE_CODE (from) == COMPONENT_REF)
     from = TREE_OPERAND (from, 1);
   if (BASELINK_P (from))
     from = BASELINK_FUNCTIONS (from);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4486b9065a16..069a05700440 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4141,8 +4141,20 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain)
 			/*overloaded_p=*/NULL, complain);
   if (!exp && code == ADDR_EXPR)
     {
-      /*  A pointer to member-function can be formed only by saying
-	  &X::mf.  */
+      if (is_overloaded_fn (xarg))
+	{
+	  tree fn = get_first_fn (xarg);
+	  if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn))
+	    {
+	      const char *type =
+		(DECL_CONSTRUCTOR_P (fn) ? "constructor" : "destructor");
+	      error ("taking address of %s %qE", type, xarg);
+	      return error_mark_node;
+	    }
+	}
+
+      /* A pointer to member-function can be formed only by saying
+	 &X::mf.  */
       if (!flag_ms_extensions && TREE_CODE (TREE_TYPE (xarg)) == METHOD_TYPE
 	  && (TREE_CODE (xarg) != OFFSET_REF || !PTRMEM_OK_P (xarg)))
 	{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2f0e185267c4..1494ae9ef68f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-05-17  Jason Merrill  <jason@redhat.com>
+
+	PR c++/40139
+	* g++.dg/template/dtor6.C: New.
+
 2009-05-17  Joseph Myers  <joseph@codesourcery.com>
 
 	* g++.dg/warn/translate-ice-1.C: New test.
diff --git a/gcc/testsuite/g++.dg/template/dtor6.C b/gcc/testsuite/g++.dg/template/dtor6.C
new file mode 100644
index 000000000000..c44b780294c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dtor6.C
@@ -0,0 +1,16 @@
+// PR c++/40139
+
+template<int> struct A
+{
+  static int i;
+};
+
+template<int N> int A<N>::i = { A::~A }; // { dg-error "non-static member function" }
+
+template class A<0>;
+
+struct X { };
+
+int i1 = X::~X;			// { dg-error "non-static member function" }
+int i2 = &X::~X;		// { dg-error "address of destructor" }
+int i3 = &A<0>::~A;		// { dg-error "address of destructor" }
-- 
GitLab