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] Fix bug 3716


Hi,
this fixes bug 3716 where we were not properly tsubsting something
which should be a pointer to member function.

Given something like
        typedef void (Func_t) ();
        template <typename T> void Foo (Func_t T::*);
        struct C;
        Foo <C> (0);

we'd make Foo's argument type a pointer to offset type of
function type. Not a pointer to member.

built & tested on i686-pc-linux-gnu, ok?

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-12-31  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/3716
	* pt.c (tsubst_aggr_type): Move pmf handling into tsubst.
	(tsubst, case POINTER_TYPE): Handle pmfs here.
	(tsubst, case OFFSET_TYPE): Check it is not an offset to
	reference. If it is offset to FUNCTION_TYPE, create a METHOD_TYPE.

Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.568
diff -c -3 -p -r1.568 pt.c
*** pt.c	2001/12/29 17:24:59	1.568
--- pt.c	2001/12/31 13:38:57
*************** tsubst_aggr_type (t, args, complain, in_
*** 5448,5459 ****
      {
      case RECORD_TYPE:
        if (TYPE_PTRMEMFUNC_P (t))
! 	{
! 	  tree r = build_ptrmemfunc_type
! 	    (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl));
! 	  return cp_build_qualified_type_real (r, TYPE_QUALS (t),
! 					       complain);
! 	}
  
        /* else fall through */
      case ENUMERAL_TYPE:
--- 5448,5454 ----
      {
      case RECORD_TYPE:
        if (TYPE_PTRMEMFUNC_P (t))
! 	return tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl);
  
        /* else fall through */
      case ENUMERAL_TYPE:
*************** tsubst_function_type (t, args, complain,
*** 6143,6149 ****
    /* The TYPE_CONTEXT is not used for function/method types.  */
    my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0);
  
!   /* Substitue the return type.  */
    return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
    if (return_type == error_mark_node)
      return error_mark_node;
--- 6138,6144 ----
    /* The TYPE_CONTEXT is not used for function/method types.  */
    my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0);
  
!   /* Substitute the return type.  */
    return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
    if (return_type == error_mark_node)
      return error_mark_node;
*************** tsubst (t, args, complain, in_decl)
*** 6558,6564 ****
        {
  	enum tree_code code;
  
! 	if (type == TREE_TYPE (t))
  	  return t;
  
  	code = TREE_CODE (t);
--- 6553,6559 ----
        {
  	enum tree_code code;
  
! 	if (type == TREE_TYPE (t) && TREE_CODE (type) != METHOD_TYPE)
  	  return t;
  
  	code = TREE_CODE (t);
*************** tsubst (t, args, complain, in_decl)
*** 6597,6603 ****
  	    return error_mark_node;
  	  }
  	else if (code == POINTER_TYPE)
! 	  r = build_pointer_type (type);
  	else
  	  r = build_reference_type (type);
  	r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
--- 6592,6602 ----
  	    return error_mark_node;
  	  }
  	else if (code == POINTER_TYPE)
! 	  {
! 	    r = build_pointer_type (type);
! 	    if (TREE_CODE (type) == METHOD_TYPE)
! 	      r = build_ptrmemfunc_type (r);
! 	  }
  	else
  	  r = build_reference_type (type);
  	r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
*************** tsubst (t, args, complain, in_decl)
*** 6625,6631 ****
  			r);
  	    return error_mark_node;
  	  }
! 	return build_offset_type (r, type);
        }
      case FUNCTION_TYPE:
      case METHOD_TYPE:
--- 6624,6653 ----
  			r);
  	    return error_mark_node;
  	  }
! 	if (TREE_CODE (type) == REFERENCE_TYPE)
! 	  {
! 	    if (complain)
! 	      error ("creating pointer to member reference type `%T'", type);
! 	    
! 	    return error_mark_node;
! 	  }
! 	my_friendly_assert (TREE_CODE (type) != METHOD_TYPE, 20011231);
! 	if (TREE_CODE (type) == FUNCTION_TYPE)
! 	  /* This is really a method type. The cv qualifiers of the
! 	     this pointer should _not_ be determined by the cv
! 	     qualifiers of the class type.  They should be held
! 	     somewhere in the FUNCTION_TYPE, but we don't do that at
! 	     the moment.  Consider
! 	        typedef void (Func) () const;
! 
! 		template <typename T1> void Foo (Func T1::*);
! 
! 	      */
! 	  return build_cplus_method_type (TYPE_MAIN_VARIANT (r),
! 					  TREE_TYPE (type),
! 					  TYPE_ARG_TYPES (type));
! 	else
! 	  return build_offset_type (r, type);
        }
      case FUNCTION_TYPE:
      case METHOD_TYPE:
// { dg-do compile }

// Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 31 Dec 2001 <nathan@codesourcery.com>

// PR 3716 tsubsting a pointer to member function did not create a
// pointer to member function.

template <class C, class T, T C::*M>
struct Closure
{
  T operator() (C & c) const { return (c.*M); }
};

template <class C, class T, T (C::* M)()>
struct Closure<C, T (), M>
{
  T operator()(C & c) const { return (c.*M)(); }
};

struct A
{
  int get();
};
  
static Closure<A, int (), & A::get> get_closure;


void Foo ()
{
  A a;
  get_closure (a);
}
// { dg-do compile }

// Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 31 Dec 2001 <nathan@codesourcery.com>

// We'd tsubst a pointer to member reference

struct A {};

template <typename T> T A::* Foo ();

void Baz ()
{
  Foo <int &> (); // { dg-error "no matching function" "" }
}

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