+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
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
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
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. */
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);
}
}
match we need to look at them, too. */
if (!matches)
{
- tree target_fn_type;
tree target_arg_types;
tree target_ret_type;
tree fns;
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;
{
tree fn = OVL_CURRENT (fns);
tree instantiation;
- tree instantiation_type;
tree targs;
if (TREE_CODE (fn) != TEMPLATE_DECL)
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);
}
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);
{
}
+/* 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;
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
+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
--- /dev/null
+// 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>;
+}