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
This commit is contained in:
Jason Merrill 2009-11-19 11:59:05 -05:00 committed by Jason Merrill
parent 4a85780b75
commit 7bead48f16
7 changed files with 88 additions and 38 deletions

View File

@ -1,3 +1,13 @@
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>
PR c++/40892

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -1,3 +1,8 @@
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>
PR libgfortran/42090

View File

@ -0,0 +1,20 @@
// 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>;
}