PR c++/561
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Nov 2009 16:59:05 +0000 (16:59 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Nov 2009 16:59:05 +0000 (16:59 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154336 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/overload/pmf2.C [new file with mode: 0644]

index 4e1f469..6a30b67 100644 (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
index c798ba2..3cf15fb 100644 (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);
        }
 
index 3aff7ec..cae259b 100644 (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);
index 599b39a..29e32c8 100644 (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;
index 3a95259..4c02f78 100644 (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
index 4e95239..bcf6d55 100644 (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
diff --git a/gcc/testsuite/g++.dg/overload/pmf2.C b/gcc/testsuite/g++.dg/overload/pmf2.C
new file mode 100644 (file)
index 0000000..e95e1f8
--- /dev/null
@@ -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>;
+}