From 6d05585b7582f089450927448e7659f62d2bdfab Mon Sep 17 00:00:00 2001
From: Mark Mitchell <mark@codesourcery.com>
Date: Wed, 6 Apr 2005 05:38:34 +0000
Subject: [PATCH] re PR c++/20734 (rejects valid pointer to member)

	PR c++/20734
	* cp-tree.def (OFFSET_REF): Correct comments.
	* init.c (build_offset_ref): Remove misleading comment.
	* typeck.c (build_unary_op): Handle pointer-to-member creation
	here, rather than ...
	(unary_complex_lvalue): ... here.

	PR c++/20734
	* g++.dg/template/ptrmem13.C: New test.

From-SVN: r97696
---
 gcc/cp/cp-tree.def                       |  6 +-
 gcc/cp/init.c                            |  3 -
 gcc/cp/typeck.c                          | 70 ++++++++----------------
 gcc/testsuite/ChangeLog                  |  5 ++
 gcc/testsuite/g++.dg/template/ptrmem13.C | 11 ++++
 5 files changed, 42 insertions(+), 53 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/ptrmem13.C

diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 1abc77bfcad3..00f2aa1db487 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -31,10 +31,8 @@ Boston, MA 02111-1307, USA.  */
       BASELINK, or TEMPLATE_ID_EXPR (corresponding to `m').
 
       The expression is a pointer-to-member if its address is taken,
-      but simply denotes a member of the object if its address isnot
-      taken.  In the latter case, resolve_offset_ref is used to
-      convert it to a representation of the member referred to by the
-      OFFSET_REF.
+      but simply denotes a member of the object if its address is not
+      taken.
       
       This form is only used during the parsing phase; once semantic
       analysis has taken place they are eliminated.
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 69089fe82691..726309acc6a0 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1551,9 +1551,6 @@ build_offset_ref (tree type, tree name, bool address_p)
       return member;
     }
 
-  /* In member functions, the form `type::name' is no longer
-     equivalent to `this->type::name', at least not until
-     resolve_offset_ref.  */
   member = build2 (OFFSET_REF, TREE_TYPE (member), decl, member);
   PTRMEM_OK_P (member) = 1;
   return member;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a3bf1c0281f7..272dc86891fc 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4026,6 +4026,29 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
 	  arg = OVL_CURRENT (arg);
 	  break;
 
+	case OFFSET_REF:
+	  /* Turn a reference to a non-static data member into a
+	     pointer-to-member.  */
+	  {
+	    tree type;
+	    tree t;
+
+	    if (!PTRMEM_OK_P (arg))
+	      return build_unary_op (code, arg, 0);
+	    
+	    t = TREE_OPERAND (arg, 1);
+	    if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+	      {
+		error ("cannot create pointer to reference member %qD", t);
+		return error_mark_node;
+	      }
+	    
+	    type = build_ptrmem_type (context_for_name_lookup (t), 
+				      TREE_TYPE (t));
+	    t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
+	    return t;
+	  }
+
 	default:
 	  break;
 	}
@@ -4182,52 +4205,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
   if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
       || TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE
       || TREE_CODE (arg) == OFFSET_REF)
-    {
-      tree t;
-
-      gcc_assert (TREE_CODE (arg) != SCOPE_REF);
-
-      if (TREE_CODE (arg) != OFFSET_REF)
-	return 0;
-
-      t = TREE_OPERAND (arg, 1);
-
-      /* Check all this code for right semantics.  */	
-      if (TREE_CODE (t) == FUNCTION_DECL)
-	{
-	  if (DECL_DESTRUCTOR_P (t))
-	    error ("taking address of destructor");
-	  return build_unary_op (ADDR_EXPR, t, 0);
-	}
-      if (TREE_CODE (t) == VAR_DECL)
-	return build_unary_op (ADDR_EXPR, t, 0);
-      else
-	{
-	  tree type;
-
-	  if (TREE_OPERAND (arg, 0)
-	      && ! is_dummy_object (TREE_OPERAND (arg, 0))
-	      && TREE_CODE (t) != FIELD_DECL)
-	    {
-	      error ("taking address of bound pointer-to-member expression");
-	      return error_mark_node;
-	    }
-	  if (!PTRMEM_OK_P (arg))
-	    return build_unary_op (code, arg, 0);
-	  
-	  if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
-	    {
-	      error ("cannot create pointer to reference member %qD", t);
-	      return error_mark_node;
-	    }
-
-	  type = build_ptrmem_type (context_for_name_lookup (t), 
-				    TREE_TYPE (t));
-	  t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
-	  return t;
-	}
-    }
-
+    return NULL_TREE;
   
   /* We permit compiler to make function calls returning
      objects of aggregate type look like lvalues.  */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3a61f76bc5cf..3c3678a2523f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-04-05  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/20734
+	* g++.dg/template/ptrmem13.C: New test.
+
 2005-04-05  Per Bothner  <per@bothner.com>
 
 	* lib/gcc.exp: Always add -fno-show-column, for now.
diff --git a/gcc/testsuite/g++.dg/template/ptrmem13.C b/gcc/testsuite/g++.dg/template/ptrmem13.C
new file mode 100644
index 000000000000..84374ea05fc0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ptrmem13.C
@@ -0,0 +1,11 @@
+// PR c++/20734
+
+struct A;
+void blah(int A::*);
+struct A{
+  int a;
+};
+template<typename T>
+void hoho(){
+  blah(&A::a);
+}
-- 
GitLab