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:
parent
4a85780b75
commit
7bead48f16
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
}
|
Loading…
Reference in New Issue