This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] PATCH for PR c++/38228

Hash: SHA1


The problem in this PR is that we allow bound pointers to member functions to be
used in a context where there should not be used.

More specifically, in the example of the PR, at some point, we try to
instantiate the member template constructor of struct A with a type argument

This happens because we are trying to instantiate A::A(T), with T being a
&B::foo and &B::foo is represented by an OFFSET_REF of type METHOD_TYPE.

So the unification of the argument of the parameter T results in a METHOD_TYPE
argument value. And that is not correct, as METHOD_TYPE is not a real c++ type.

This patch prevents template arguments from being unified to METHOD_TYPE. That
fixes the crash reported in the PR.

In addition to that, the patch tries to provide a meaningful error message that
is consistent with what g++ provides in similar cases of wrong usage of bound
pointer to member functions.

The patch bootstraps and passes regtests on 4.3, 4.4 and 4.5.

OK to apply to those branches once 4.4 is released ?


Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Remi -

commit cf11f811fe45a7c3fcf2767bd0c302503c853fb2
Author: Dodji Seketeli <>
Date:   Tue Apr 14 15:28:13 2009 +0200

    Fix candidate for PR38228
    2009-04-14  Dodji Seketeli  <>
    	PR c++/38228
    	* pt.c (unify): Do not allow the result of a template argument
    	deduction to be a METHOD_TYPE.
    	* ocvt.c (cp_convert): Report a meaningful error for non-valid use
    	of pointer to member functions during conversions.
    	* call.c (build_new_op): Report a meaningful error for non-valid
    	use of pointer to member functions in binary expressions.
    	* typeck.c (invalid_nonstatic_memfn_p): Do not crash when EXPR is
    2009-04-14  Dodji Seketeli  <>
    	PR c++/38228
    	* g++.dg/expr/bound-mem-fun.C: New test.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c942712..bc692c0 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4067,10 +4067,22 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
-	  if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error))
+	  if (complain & tf_error)
-	      op_error (code, code2, arg1, arg2, arg3, "no match");
-	      print_z_candidates (candidates);
+	      /* If one of the arguments of the operator represents
+	         an invalid use of member function pointer, try to report
+		 a meaningful error ...  */
+	      if (invalid_nonstatic_memfn_p (arg1, tf_error)
+		  || invalid_nonstatic_memfn_p (arg2, tf_error)
+		  || invalid_nonstatic_memfn_p (arg3, tf_error))
+		;
+	      else if (flags & LOOKUP_COMPLAIN)
+		{
+		  /* ... Otherwise, report the more generic
+		     "no matching operator found" error */
+		  op_error (code, code2, arg1, arg2, arg3, "no match");
+		  print_z_candidates (candidates);
+		}
 	  result = error_mark_node;
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index fed4ab2..467c178 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -759,6 +759,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
 	return build_cplus_new (type, ctor);
+  /* If the conversion failed and expr was an invalid use of pointer to
+     member function, try to report a meaningful error.  */
+  if (invalid_nonstatic_memfn_p (expr, tf_warning_or_error))
+    return error_mark_node;
   if (flags & LOOKUP_COMPLAIN)
     error ("conversion from %qT to non-scalar type %qT requested",
 	   TREE_TYPE (expr), type);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8dd3579..a5b8b63 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13578,6 +13578,13 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  && !template_parameter_pack_p (parm))
 	return 1;
+      /* If the argument deduction results is a METHOD_TYPE,
+         then there is a problem.
+         METHOD_TYPE doesn't map to any real C++ type the result of
+	 the deduction can not be of that type.  */
+      if (TREE_CODE (arg) == METHOD_TYPE)
+	return 1;
       TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
       return 0;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index fe791f3..1152c80 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1508,7 +1508,7 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op, bool complain)
 invalid_nonstatic_memfn_p (const_tree expr, tsubst_flags_t complain)
       if (complain & tf_error)
         error ("invalid use of non-static member function");
diff --git a/gcc/testsuite/g++.dg/expr/bound-mem-fun.C b/gcc/testsuite/g++.dg/expr/bound-mem-fun.C
new file mode 100644
index 0000000..9e699b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/bound-mem-fun.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <>
+// Origin PR c++/38228
+// { dg-do "compile" }
+struct A
+  A ();
+  template<typename T> A(T);
+struct B
+  int foo();
+A a = B().*(&B::foo); // { dg-error "invalid use of non-static member function" }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]