From 4d5c38fc8df3eb086dda3acfbe37ec06d7683698 Mon Sep 17 00:00:00 2001 From: jason Date: Thu, 19 Nov 2009 16:59:05 +0000 Subject: [PATCH] PR c++/561 * decl.c (static_fn_type): Split out... (revert_static_member_fn): ...from here. * cp-tree.h: Declare it. * class.c (resolve_address_of_overloaded_function): Use it to compare pointers to member functions. * typeck.c (build_static_cast_1): Call instantiate_type. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154336 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 10 +++++++++ gcc/cp/class.c | 39 ++++++++++---------------------- gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 43 +++++++++++++++++++++++++++--------- gcc/cp/typeck.c | 8 +++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/overload/pmf2.C | 20 +++++++++++++++++ 7 files changed, 88 insertions(+), 38 deletions(-) create mode 100644 gcc/testsuite/g++.dg/overload/pmf2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4e1f469..6a30b67 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2009-11-19 Jason Merrill + + PR c++/561 + * decl.c (static_fn_type): Split out... + (revert_static_member_fn): ...from here. + * cp-tree.h: Declare it. + * class.c (resolve_address_of_overloaded_function): Use it to compare + pointers to member functions. + * typeck.c (build_static_cast_1): Call instantiate_type. + 2009-11-18 Shujing Zhao PR c++/40892 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c798ba2..3cf15fb 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6065,6 +6065,7 @@ resolve_address_of_overloaded_function (tree target_type, interoperability with most_specialized_instantiation. */ tree matches = NULL_TREE; tree fn; + tree target_fn_type; /* By the time we get here, we should be seeing only real pointer-to-member types, not the internal POINTER_TYPE to @@ -6096,6 +6097,15 @@ resolve_address_of_overloaded_function (tree target_type, return error_mark_node; } + /* Non-member functions and static member functions match targets of type + "pointer-to-function" or "reference-to-function." Nonstatic member + functions match targets of type "pointer-to-member-function;" the + function type of the pointer to member is used to select the member + function from the set of overloaded member functions. + + So figure out the FUNCTION_TYPE that we want to match against. */ + target_fn_type = static_fn_type (target_type); + /* If we can find a non-template function that matches, we can just use it. There's no point in generating template instantiations if we're just going to throw them out anyhow. But, of course, we @@ -6107,7 +6117,6 @@ resolve_address_of_overloaded_function (tree target_type, for (fns = overload; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); - tree fntype; if (TREE_CODE (fn) == TEMPLATE_DECL) /* We're not looking for templates just yet. */ @@ -6125,13 +6134,7 @@ resolve_address_of_overloaded_function (tree target_type, continue; /* See if there's a match. */ - fntype = TREE_TYPE (fn); - if (is_ptrmem) - fntype = build_ptrmemfunc_type (build_pointer_type (fntype)); - else if (!is_reference) - fntype = build_pointer_type (fntype); - - if (can_convert_arg (target_type, fntype, fn, LOOKUP_NORMAL)) + if (same_type_p (target_fn_type, static_fn_type (fn))) matches = tree_cons (fn, NULL_TREE, matches); } } @@ -6141,7 +6144,6 @@ resolve_address_of_overloaded_function (tree target_type, match we need to look at them, too. */ if (!matches) { - tree target_fn_type; tree target_arg_types; tree target_ret_type; tree fns; @@ -6149,18 +6151,9 @@ resolve_address_of_overloaded_function (tree target_type, unsigned int nargs, ia; tree arg; - if (is_ptrmem) - target_fn_type - = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (target_type)); - else - target_fn_type = TREE_TYPE (target_type); target_arg_types = TYPE_ARG_TYPES (target_fn_type); target_ret_type = TREE_TYPE (target_fn_type); - /* Never do unification on the 'this' parameter. */ - if (TREE_CODE (target_fn_type) == METHOD_TYPE) - target_arg_types = TREE_CHAIN (target_arg_types); - nargs = list_length (target_arg_types); args = XALLOCAVEC (tree, nargs); for (arg = target_arg_types, ia = 0; @@ -6173,7 +6166,6 @@ resolve_address_of_overloaded_function (tree target_type, { tree fn = OVL_CURRENT (fns); tree instantiation; - tree instantiation_type; tree targs; if (TREE_CODE (fn) != TEMPLATE_DECL) @@ -6201,14 +6193,7 @@ resolve_address_of_overloaded_function (tree target_type, continue; /* See if there's a match. */ - instantiation_type = TREE_TYPE (instantiation); - if (is_ptrmem) - instantiation_type = - build_ptrmemfunc_type (build_pointer_type (instantiation_type)); - else if (!is_reference) - instantiation_type = build_pointer_type (instantiation_type); - if (can_convert_arg (target_type, instantiation_type, instantiation, - LOOKUP_NORMAL)) + if (same_type_p (target_fn_type, static_fn_type (instantiation))) matches = tree_cons (instantiation, fn, matches); } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3aff7ec..cae259b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4610,6 +4610,7 @@ extern void maybe_register_incomplete_var (tree); extern void maybe_commonize_var (tree); extern void complete_vars (tree); extern void finish_stmt (void); +extern tree static_fn_type (tree); extern void revert_static_member_fn (tree); extern void fixup_anonymous_aggr (tree); extern int check_static_variable_definition (tree, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 599b39a..29e32c8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -12812,26 +12812,47 @@ finish_stmt (void) { } +/* Return the FUNCTION_TYPE that corresponds to MEMFNTYPE, which can be a + FUNCTION_DECL, METHOD_TYPE, FUNCTION_TYPE, pointer or reference to + METHOD_TYPE or FUNCTION_TYPE, or pointer to member function. */ + +tree +static_fn_type (tree memfntype) +{ + tree fntype; + tree args; + int quals; + + if (TYPE_PTRMEMFUNC_P (memfntype)) + memfntype = TYPE_PTRMEMFUNC_FN_TYPE (memfntype); + if (POINTER_TYPE_P (memfntype) + || TREE_CODE (memfntype) == FUNCTION_DECL) + memfntype = TREE_TYPE (memfntype); + if (TREE_CODE (memfntype) == FUNCTION_TYPE) + return memfntype; + gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE); + args = TYPE_ARG_TYPES (memfntype); + fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args)); + quals = cp_type_quals (TREE_TYPE (TREE_VALUE (args))); + fntype = build_qualified_type (fntype, quals); + fntype = (cp_build_type_attribute_variant + (fntype, TYPE_ATTRIBUTES (memfntype))); + fntype = (build_exception_variant + (fntype, TYPE_RAISES_EXCEPTIONS (memfntype))); + return fntype; +} + /* DECL was originally constructed as a non-static member function, but turned out to be static. Update it accordingly. */ void revert_static_member_fn (tree decl) { - tree tmp; - tree function = TREE_TYPE (decl); - tree args = TYPE_ARG_TYPES (function); + TREE_TYPE (decl) = static_fn_type (decl); - if (cp_type_quals (TREE_TYPE (TREE_VALUE (args))) - != TYPE_UNQUALIFIED) + if (cp_type_quals (TREE_TYPE (decl)) != TYPE_UNQUALIFIED) error ("static member function %q#D declared with type qualifiers", decl); - args = TREE_CHAIN (args); - tmp = build_function_type (TREE_TYPE (function), args); - tmp = build_qualified_type (tmp, cp_type_quals (function)); - tmp = build_exception_variant (tmp, - TYPE_RAISES_EXCEPTIONS (function)); - TREE_TYPE (decl) = tmp; if (DECL_ARGUMENTS (decl)) DECL_ARGUMENTS (decl) = TREE_CHAIN (DECL_ARGUMENTS (decl)); DECL_STATIC_FUNCTION_P (decl) = 1; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 3a95259..4c02f78 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5346,6 +5346,14 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, orig = expr; + /* Resolve overloaded address here rather than once in + implicit_conversion and again in the inverse code below. */ + if (TYPE_PTRMEMFUNC_P (type) && type_unknown_p (expr)) + { + expr = instantiate_type (type, expr, complain); + intype = TREE_TYPE (expr); + } + /* [expr.static.cast] An expression e can be explicitly converted to a type T using a diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4e95239..bcf6d55 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-11-19 Jason Merrill + + PR c++/561 + * g++.dg/overload/pmf2.C: New. + 2009-11-18 Jerry DeLisle PR libgfortran/42090 diff --git a/gcc/testsuite/g++.dg/overload/pmf2.C b/gcc/testsuite/g++.dg/overload/pmf2.C new file mode 100644 index 0000000..e95e1f8 --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/pmf2.C @@ -0,0 +1,20 @@ +// PR c++/561 + +class A { }; + +struct B : public A +{ + void foo (); + void foo (int); + template + void bar (T); + template + void bar (T, T); +}; + +int main () +{ + void (A::*f1)() = (void (A::*)()) &B::foo; + void (A::*f2)(int) = (void (A::*)(int)) &B::bar; + void (A::*f3)(int) = (void (A::*)(int)) &B::bar; +} -- 2.7.4