]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/48594 (Rejects valid with pointer-to-member in template)
authorJason Merrill <jason@redhat.com>
Thu, 21 Apr 2011 02:57:28 +0000 (22:57 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 21 Apr 2011 02:57:28 +0000 (22:57 -0400)
PR c++/48594
* decl2.c (build_offset_ref_call_from_tree): Fix calling a functor
or pointer to (non-member) function.

From-SVN: r172804

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/operator11.C [new file with mode: 0644]

index e1462664124b765fabc5160a20e15de6c8085fff..0ae5b3ca2c5f7e896f853cbbb6cb296b677e69da 100644 (file)
@@ -1,3 +1,9 @@
+2011-04-20  Jason Merrill  <jason@redhat.com>
+
+       PR c++/48594
+       * decl2.c (build_offset_ref_call_from_tree): Fix calling a functor
+       or pointer to (non-member) function.
+
 2011-04-16  Release Manager
 
        * GCC 4.4.6 released.
index bc4586840140487d9b01c59b14c80359dde0c23a..7bfd59d736e485d0122e9ece7e85e832f9cd25c2 100644 (file)
@@ -145,7 +145,6 @@ static tree convert_like_real (conversion *, tree, tree, int, int, bool,
                               bool, tsubst_flags_t);
 static void op_error (enum tree_code, enum tree_code, tree, tree,
                      tree, const char *);
-static tree build_object_call (tree, tree, tsubst_flags_t);
 static tree resolve_args (tree);
 static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
 static void print_z_candidate (const char *, struct z_candidate *);
@@ -3194,7 +3193,7 @@ build_operator_new_call (tree fnname, tree args,
    return build_over_call (cand, LOOKUP_NORMAL, tf_warning_or_error);
 }
 
-static tree
+tree
 build_object_call (tree obj, tree args, tsubst_flags_t complain)
 {
   struct z_candidate *candidates = 0, *cand;
index 3a3f5f5cab16a063b0763eb7bdd36c2023dcf87e..7b244026a567b2491f75e533061a0a4d45dbeb90 100644 (file)
@@ -4193,6 +4193,7 @@ extern tree build_new_function_call               (tree, tree, bool,
                                                 tsubst_flags_t);
 extern tree build_operator_new_call            (tree, tree, tree *, tree *,
                                                 tree *);
+extern tree build_object_call                  (tree, tree, tsubst_flags_t);
 extern tree build_new_method_call              (tree, tree, tree, tree, int,
                                                 tree *, tsubst_flags_t);
 extern tree build_special_member_call          (tree, tree, tree, tree, int,
index ddd219533dfb0265259c7ca919fc1c3ca83f61e7..947256baf43c8a30ebd52cbc08940e5f3e4232cb 100644 (file)
@@ -3725,9 +3725,12 @@ build_offset_ref_call_from_tree (tree fn, tree args)
         because we depend on the form of FN.  */
       args = build_non_dependent_args (args);
       object = build_non_dependent_expr (object);
-      if (TREE_CODE (fn) == DOTSTAR_EXPR)
-       object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error);
-      args = tree_cons (NULL_TREE, object, args);
+      if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+       {
+         if (TREE_CODE (fn) == DOTSTAR_EXPR)
+           object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error);
+         args = tree_cons (NULL_TREE, object, args);
+       }
       /* Now that the arguments are done, transform FN.  */
       fn = build_non_dependent_expr (fn);
     }
@@ -3747,7 +3750,10 @@ build_offset_ref_call_from_tree (tree fn, tree args)
       args = tree_cons (NULL_TREE, object_addr, args);
     }
 
-  expr = cp_build_function_call (fn, args, tf_warning_or_error);
+  if (CLASS_TYPE_P (TREE_TYPE (fn)))
+    expr = build_object_call (fn, args, tf_warning_or_error);
+  else
+    expr = cp_build_function_call (fn, args, tf_warning_or_error);
   if (processing_template_decl && expr != error_mark_node)
     return build_min_non_dep_call_list (expr, orig_fn, orig_args);
   return expr;
index a1059e6c25dff35587c94b19df3b959ceba3174e..223467dd44ba7268cc74629f0e80b34ab2b0713b 100644 (file)
@@ -1,3 +1,7 @@
+2011-04-20  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/template/operator11.C: New.
+
 2011-04-16  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from 4.6 branch
diff --git a/gcc/testsuite/g++.dg/template/operator11.C b/gcc/testsuite/g++.dg/template/operator11.C
new file mode 100644 (file)
index 0000000..8d6b77a
--- /dev/null
@@ -0,0 +1,25 @@
+// PR c++/48594
+// Test for uses of (X->*Y)() that don't actually involve a
+// pointer to member function.
+
+struct A { } a;
+struct B { } b;
+struct C * cp;
+
+struct Func { void operator()(); };
+Func operator->* (A, int);
+
+typedef void (*pfn)();
+pfn operator->* (B, int);
+
+pfn C::*cpfn;
+Func C::*cfunc;
+
+template <class T>
+void f()
+{
+  (a->*1)();
+  (b->*1)();
+  (cp->*cpfn)();
+  (cp->*cfunc)();
+}