This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 20734


This patch fixes PR c++/20734, a problem with pointers-to-members in
templates.  Most of this patch is moving the part of front end that
handles creating a pointer-to-member from "&" applied to "X::y" out of
unary_complex_lvalue (where it should never have been) to
build_unary_op, where it clearly belongs.  I also simplified that code
a bit in the process of moving it.

Tested on x86_64-unknown-linux-gnu, applied on 4.0 branch and
mainline. 

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
 
2005-04-05  Mark Mitchell  <mark@codesourcery.com>

	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.

2005-04-05  Mark Mitchell  <mark@codesourcery.com>

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

Index: testsuite/g++.dg/template/ptrmem13.C
===================================================================
RCS file: testsuite/g++.dg/template/ptrmem13.C
diff -N testsuite/g++.dg/template/ptrmem13.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/ptrmem13.C	6 Apr 2005 02:32:26 -0000
***************
*** 0 ****
--- 1,11 ----
+ // PR c++/20734
+ 
+ struct A;
+ void blah(int A::*);
+ struct A{
+   int a;
+ };
+ template<typename T>
+ void hoho(){
+   blah(&A::a);
+ }
Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.94
diff -c -5 -p -r1.94 cp-tree.def
*** cp/cp-tree.def	11 Feb 2005 16:28:37 -0000	1.94
--- cp/cp-tree.def	6 Apr 2005 02:32:26 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 29,42 ****
        a non-static member.  In this case, operand 0 will be a TYPE
        (corresponding to `A') and operand 1 will be a FIELD_DECL,
        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.
        
        This form is only used during the parsing phase; once semantic
        analysis has taken place they are eliminated.
  
     2. An expression of the form `x.*p'.  In this case, operand 0 will
--- 29,40 ----
        a non-static member.  In this case, operand 0 will be a TYPE
        (corresponding to `A') and operand 1 will be a FIELD_DECL,
        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 is not
!       taken.
        
        This form is only used during the parsing phase; once semantic
        analysis has taken place they are eliminated.
  
     2. An expression of the form `x.*p'.  In this case, operand 0 will
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.412.2.3
diff -c -5 -p -r1.412.2.3 init.c
*** cp/init.c	22 Mar 2005 09:10:49 -0000	1.412.2.3
--- cp/init.c	6 Apr 2005 02:32:27 -0000
*************** build_offset_ref (tree type, tree name, 
*** 1549,1561 ****
  	  return error_mark_node;
  	}
        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;
  }
  
--- 1549,1558 ----
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.616.2.3
diff -c -5 -p -r1.616.2.3 typeck.c
*** cp/typeck.c	25 Mar 2005 22:54:48 -0000	1.616.2.3
--- cp/typeck.c	6 Apr 2005 02:32:27 -0000
*************** build_unary_op (enum tree_code code, tre
*** 4024,4033 ****
--- 4024,4056 ----
  
  	case OVERLOAD:
  	  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;
  	}
  
        /* Allow the address of a constructor if all the elements
*************** unary_complex_lvalue (enum tree_code cod
*** 4180,4235 ****
      }
  
    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;
! 	}
!     }
! 
    
    /* We permit compiler to make function calls returning
       objects of aggregate type look like lvalues.  */
    {
      tree targ = arg;
--- 4203,4213 ----
      }
  
    if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
        || TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE
        || TREE_CODE (arg) == OFFSET_REF)
!     return NULL_TREE;
    
    /* We permit compiler to make function calls returning
       objects of aggregate type look like lvalues.  */
    {
      tree targ = arg;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]