Commit 7bead48f by Jason Merrill Committed by Jason Merrill

re PR c++/561 (std:unclear about Overloaded Function Pointer resolution)

	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.

From-SVN: r154336
parent 4a85780b
2009-11-19 Jason Merrill <jason@redhat.com>
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 <pearly.zhao@oracle.com> 2009-11-18 Shujing Zhao <pearly.zhao@oracle.com>
PR c++/40892 PR c++/40892
......
...@@ -6065,6 +6065,7 @@ resolve_address_of_overloaded_function (tree target_type, ...@@ -6065,6 +6065,7 @@ resolve_address_of_overloaded_function (tree target_type,
interoperability with most_specialized_instantiation. */ interoperability with most_specialized_instantiation. */
tree matches = NULL_TREE; tree matches = NULL_TREE;
tree fn; tree fn;
tree target_fn_type;
/* By the time we get here, we should be seeing only real /* By the time we get here, we should be seeing only real
pointer-to-member types, not the internal POINTER_TYPE to pointer-to-member types, not the internal POINTER_TYPE to
...@@ -6096,6 +6097,15 @@ resolve_address_of_overloaded_function (tree target_type, ...@@ -6096,6 +6097,15 @@ resolve_address_of_overloaded_function (tree target_type,
return error_mark_node; 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 /* If we can find a non-template function that matches, we can just
use it. There's no point in generating template instantiations use it. There's no point in generating template instantiations
if we're just going to throw them out anyhow. But, of course, we 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, ...@@ -6107,7 +6117,6 @@ resolve_address_of_overloaded_function (tree target_type,
for (fns = overload; fns; fns = OVL_NEXT (fns)) for (fns = overload; fns; fns = OVL_NEXT (fns))
{ {
tree fn = OVL_CURRENT (fns); tree fn = OVL_CURRENT (fns);
tree fntype;
if (TREE_CODE (fn) == TEMPLATE_DECL) if (TREE_CODE (fn) == TEMPLATE_DECL)
/* We're not looking for templates just yet. */ /* We're not looking for templates just yet. */
...@@ -6125,13 +6134,7 @@ resolve_address_of_overloaded_function (tree target_type, ...@@ -6125,13 +6134,7 @@ resolve_address_of_overloaded_function (tree target_type,
continue; continue;
/* See if there's a match. */ /* See if there's a match. */
fntype = TREE_TYPE (fn); if (same_type_p (target_fn_type, static_fn_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))
matches = tree_cons (fn, NULL_TREE, matches); matches = tree_cons (fn, NULL_TREE, matches);
} }
} }
...@@ -6141,7 +6144,6 @@ resolve_address_of_overloaded_function (tree target_type, ...@@ -6141,7 +6144,6 @@ resolve_address_of_overloaded_function (tree target_type,
match we need to look at them, too. */ match we need to look at them, too. */
if (!matches) if (!matches)
{ {
tree target_fn_type;
tree target_arg_types; tree target_arg_types;
tree target_ret_type; tree target_ret_type;
tree fns; tree fns;
...@@ -6149,18 +6151,9 @@ resolve_address_of_overloaded_function (tree target_type, ...@@ -6149,18 +6151,9 @@ resolve_address_of_overloaded_function (tree target_type,
unsigned int nargs, ia; unsigned int nargs, ia;
tree arg; 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_arg_types = TYPE_ARG_TYPES (target_fn_type);
target_ret_type = TREE_TYPE (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); nargs = list_length (target_arg_types);
args = XALLOCAVEC (tree, nargs); args = XALLOCAVEC (tree, nargs);
for (arg = target_arg_types, ia = 0; for (arg = target_arg_types, ia = 0;
...@@ -6173,7 +6166,6 @@ resolve_address_of_overloaded_function (tree target_type, ...@@ -6173,7 +6166,6 @@ resolve_address_of_overloaded_function (tree target_type,
{ {
tree fn = OVL_CURRENT (fns); tree fn = OVL_CURRENT (fns);
tree instantiation; tree instantiation;
tree instantiation_type;
tree targs; tree targs;
if (TREE_CODE (fn) != TEMPLATE_DECL) if (TREE_CODE (fn) != TEMPLATE_DECL)
...@@ -6201,14 +6193,7 @@ resolve_address_of_overloaded_function (tree target_type, ...@@ -6201,14 +6193,7 @@ resolve_address_of_overloaded_function (tree target_type,
continue; continue;
/* See if there's a match. */ /* See if there's a match. */
instantiation_type = TREE_TYPE (instantiation); if (same_type_p (target_fn_type, static_fn_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))
matches = tree_cons (instantiation, fn, matches); matches = tree_cons (instantiation, fn, matches);
} }
......
...@@ -4610,6 +4610,7 @@ extern void maybe_register_incomplete_var (tree); ...@@ -4610,6 +4610,7 @@ extern void maybe_register_incomplete_var (tree);
extern void maybe_commonize_var (tree); extern void maybe_commonize_var (tree);
extern void complete_vars (tree); extern void complete_vars (tree);
extern void finish_stmt (void); extern void finish_stmt (void);
extern tree static_fn_type (tree);
extern void revert_static_member_fn (tree); extern void revert_static_member_fn (tree);
extern void fixup_anonymous_aggr (tree); extern void fixup_anonymous_aggr (tree);
extern int check_static_variable_definition (tree, tree); extern int check_static_variable_definition (tree, tree);
......
...@@ -12812,26 +12812,47 @@ finish_stmt (void) ...@@ -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, /* DECL was originally constructed as a non-static member function,
but turned out to be static. Update it accordingly. */ but turned out to be static. Update it accordingly. */
void void
revert_static_member_fn (tree decl) revert_static_member_fn (tree decl)
{ {
tree tmp; TREE_TYPE (decl) = static_fn_type (decl);
tree function = TREE_TYPE (decl);
tree args = TYPE_ARG_TYPES (function);
if (cp_type_quals (TREE_TYPE (TREE_VALUE (args))) if (cp_type_quals (TREE_TYPE (decl)) != TYPE_UNQUALIFIED)
!= TYPE_UNQUALIFIED)
error ("static member function %q#D declared with type qualifiers", decl); 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)) if (DECL_ARGUMENTS (decl))
DECL_ARGUMENTS (decl) = TREE_CHAIN (DECL_ARGUMENTS (decl)); DECL_ARGUMENTS (decl) = TREE_CHAIN (DECL_ARGUMENTS (decl));
DECL_STATIC_FUNCTION_P (decl) = 1; DECL_STATIC_FUNCTION_P (decl) = 1;
......
...@@ -5346,6 +5346,14 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -5346,6 +5346,14 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
orig = expr; 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] /* [expr.static.cast]
An expression e can be explicitly converted to a type T using a An expression e can be explicitly converted to a type T using a
......
2009-11-19 Jason Merrill <jason@redhat.com>
PR c++/561
* g++.dg/overload/pmf2.C: New.
2009-11-18 Jerry DeLisle <jvdelisle@gcc.gnu.org> 2009-11-18 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/42090 PR libgfortran/42090
......
// PR c++/561
class A { };
struct B : public A
{
void foo ();
void foo (int);
template <class T>
void bar (T);
template <class T>
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<int>;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment