aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-11-19 11:59:05 -0500
committerJason Merrill <jason@gcc.gnu.org>2009-11-19 11:59:05 -0500
commit7bead48f160d4faab372aeab8a5200c5c21d2523 (patch)
tree918b5da9a9ebc906d543b57fb0a5e50e3dd5076f /gcc/cp
parent4a85780b75143fa28bc26ce508eafa95c5f5b3e8 (diff)
downloadgcc-7bead48f160d4faab372aeab8a5200c5c21d2523.zip
gcc-7bead48f160d4faab372aeab8a5200c5c21d2523.tar.gz
gcc-7bead48f160d4faab372aeab8a5200c5c21d2523.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/class.c39
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c43
-rw-r--r--gcc/cp/typeck.c8
5 files changed, 63 insertions, 38 deletions
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 <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
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