This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix bug 3716
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 31 Dec 2001 14:02:33 +0000
- Subject: [C++ PATCH] Fix bug 3716
- Organization: Codesourcery LLC
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" "" }
}