diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2002-01-02 13:55:23 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2002-01-02 13:55:23 +0000 |
commit | 46c895ac0b9468a53f08e1875b13aca83227ec5d (patch) | |
tree | 1e7c6a62af4480d37032a64370d64099ab6fab12 /gcc | |
parent | 833aa4c4149ce0fa84968a03fe51a13575381d79 (diff) | |
download | gcc-46c895ac0b9468a53f08e1875b13aca83227ec5d.zip gcc-46c895ac0b9468a53f08e1875b13aca83227ec5d.tar.gz gcc-46c895ac0b9468a53f08e1875b13aca83227ec5d.tar.bz2 |
re PR c++/3716 (Template parameters that are pointers to member functions)
cp:
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.
testsuite:
* g++.dg/template/ptrmem1.C: New test.
* g++.dg/template/ptrmem2.C: New test.
From-SVN: r48471
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/pt.c | 42 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/ptrmem1.C | 33 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/ptrmem2.C | 15 |
5 files changed, 91 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4751ae9..c259242 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2002-01-02 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. + +2002-01-02 Nathan Sidwell <nathan@codesourcery.com> + PR c++/35 * cp-tree.h (DECL_LANG_FLAG_0): Used for PARM_DECL too. (DECL_TEMPLATE_PARM_P): A PARM_DECL might be one too. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4f20635..a60cacf 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5452,12 +5452,7 @@ tsubst_aggr_type (t, args, complain, in_decl, entering_scope) { 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); - } + return tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl); /* else fall through */ case ENUMERAL_TYPE: @@ -6150,7 +6145,7 @@ tsubst_function_type (t, args, complain, in_decl) /* The TYPE_CONTEXT is not used for function/method types. */ my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0); - /* Substitue the return type. */ + /* Substitute the return type. */ return_type = tsubst (TREE_TYPE (t), args, complain, in_decl); if (return_type == error_mark_node) return error_mark_node; @@ -6565,7 +6560,7 @@ tsubst (t, args, complain, in_decl) { enum tree_code code; - if (type == TREE_TYPE (t)) + if (type == TREE_TYPE (t) && TREE_CODE (type) != METHOD_TYPE) return t; code = TREE_CODE (t); @@ -6604,7 +6599,11 @@ tsubst (t, args, complain, in_decl) return error_mark_node; } else if (code == POINTER_TYPE) - r = build_pointer_type (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); @@ -6632,7 +6631,30 @@ tsubst (t, args, complain, in_decl) r); return error_mark_node; } - return build_offset_type (r, type); + 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: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d08a707..cdd244e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2002-01-02 Nathan Sidwell <nathan@codesourcery.com> + * g++.dg/template/ptrmem1.C: New test. + * g++.dg/template/ptrmem2.C: New test. + * g++.dg/template/ntp.C: New test. * g++.dg/other/component1.C: New test. diff --git a/gcc/testsuite/g++.dg/template/ptrmem1.C b/gcc/testsuite/g++.dg/template/ptrmem1.C new file mode 100644 index 0000000..ebd6a20 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ptrmem1.C @@ -0,0 +1,33 @@ +// { 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); +} diff --git a/gcc/testsuite/g++.dg/template/ptrmem2.C b/gcc/testsuite/g++.dg/template/ptrmem2.C new file mode 100644 index 0000000..23a4ad9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ptrmem2.C @@ -0,0 +1,15 @@ +// { 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" "" } +} |