Hi,

Manuel did most of the work for this rather simple issue filed by Tom: essentially, invalid_nonstatic_memfn_p gets a location_t parameter which is used to pass the location of the place where the use of the nonstatic member function is indeed invalid. Besides that, while working on the bug we noticed that we must be careful with exprs which aren't DECLs.

Tested x86_64-linux.

Thanks,
Paolo.

////////////////////////////
2015-05-18  Manuel López-Ibáñez  <m...@gcc.gnu.org>
            Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/66130
        * typeck.c (invalid_nonstatic_memfn_p): Add location_t parameter and
        use it in the diagnostic.
        (decay_conversion): Adjust call.
        * semantics.c (finish_decltype_type): Likewise.
        * call.c (resolve_args, build_new_op_1,
        perform_implicit_conversion_flags): Adjust calls.
        * cvt.c (ocp_convert, convert_to_void): Likewise.
        * cp-tree.h (invalid_nonstatic_memfn_p): Update declaration.

2015-05-18  Manuel López-Ibáñez  <m...@gcc.gnu.org>
            Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/66130
        * g++.dg/other/pr66130.C: New.
        * g++.dg/cpp0x/pr66130.C: Likewise.
Index: cp/call.c
===================================================================
--- cp/call.c   (revision 223295)
+++ cp/call.c   (working copy)
@@ -3941,7 +3941,7 @@ resolve_args (vec<tree, va_gc> *args, tsubst_flags
            error ("invalid use of void expression");
          return NULL;
        }
-      else if (invalid_nonstatic_memfn_p (arg, complain))
+      else if (invalid_nonstatic_memfn_p (input_location, arg, complain))
        return NULL;
     }
   return args;
@@ -5542,9 +5542,9 @@ build_new_op_1 (location_t loc, enum tree_code cod
                /* 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))
+             if (invalid_nonstatic_memfn_p (loc, arg1, tf_error)
+                   || invalid_nonstatic_memfn_p (loc, arg2, tf_error)
+                   || invalid_nonstatic_memfn_p (loc, arg3, tf_error))
                  /* We displayed the error message.  */;
                else
                  {
@@ -9409,7 +9409,7 @@ perform_implicit_conversion_flags (tree type, tree
             Call instantiate_type to get good error messages.  */
          if (TREE_TYPE (expr) == unknown_type_node)
            instantiate_type (type, expr, complain);
-         else if (invalid_nonstatic_memfn_p (expr, complain))
+         else if (invalid_nonstatic_memfn_p (loc, expr, complain))
            /* We gave an error.  */;
          else
            error_at (loc, "could not convert %qE from %qT to %qT", expr,
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 223295)
+++ cp/cp-tree.h        (working copy)
@@ -6282,7 +6282,8 @@ extern tree build_address                 (tree);
 extern tree build_nop                          (tree, tree);
 extern tree non_reference                      (tree);
 extern tree lookup_anon_field                  (tree, tree);
-extern bool invalid_nonstatic_memfn_p          (tree, tsubst_flags_t);
+extern bool invalid_nonstatic_memfn_p          (location_t, tree,
+                                                tsubst_flags_t);
 extern tree convert_member_func_to_ptr         (tree, tree, tsubst_flags_t);
 extern tree convert_ptrmem                     (tree, tree, bool, bool,
                                                 tsubst_flags_t);
Index: cp/cvt.c
===================================================================
--- cp/cvt.c    (revision 223295)
+++ cp/cvt.c    (working copy)
@@ -902,7 +902,7 @@ ocp_convert (tree type, tree expr, int convtype, i
     {
       /* 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, complain))
+      if (invalid_nonstatic_memfn_p (loc, expr, complain))
        /* We displayed the error message.  */;
       else
        error_at (loc, "conversion from %qT to non-scalar type %qT requested",
@@ -960,7 +960,7 @@ convert_to_void (tree expr, impl_conv_void implici
 
   if (!TREE_TYPE (expr))
     return expr;
-  if (invalid_nonstatic_memfn_p (expr, complain))
+  if (invalid_nonstatic_memfn_p (loc, expr, complain))
     return error_mark_node;
   if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
     {
Index: cp/semantics.c
===================================================================
--- cp/semantics.c      (revision 223295)
+++ cp/semantics.c      (working copy)
@@ -7242,7 +7242,7 @@ finish_decltype_type (tree expr, bool id_expressio
 
   expr = resolve_nondeduced_context (expr);
 
-  if (invalid_nonstatic_memfn_p (expr, complain))
+  if (invalid_nonstatic_memfn_p (input_location, expr, complain))
     return error_mark_node;
 
   if (type_unknown_p (expr))
Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 223295)
+++ cp/typeck.c (working copy)
@@ -1815,7 +1815,7 @@ cxx_alignas_expr (tree e)
    violates these rules.  */
 
 bool
-invalid_nonstatic_memfn_p (tree expr, tsubst_flags_t complain)
+invalid_nonstatic_memfn_p (location_t loc, tree expr, tsubst_flags_t complain)
 {
   if (expr == NULL_TREE)
     return false;
@@ -1827,7 +1827,17 @@ bool
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (expr))
     {
       if (complain & tf_error)
-        error ("invalid use of non-static member function");
+       {
+         if (DECL_P (expr))
+           {
+             error_at (loc, "invalid use of non-static member function %qD",
+                       expr);
+             inform (DECL_SOURCE_LOCATION (expr), "declared here");
+           }
+         else
+           error_at (loc, "invalid use of non-static member function of "
+                     "type %qT", TREE_TYPE (expr));
+       }
       return true;
     }
   return false;
@@ -1951,7 +1961,7 @@ decay_conversion (tree exp, tsubst_flags_t complai
        error_at (loc, "void value not ignored as it ought to be");
       return error_mark_node;
     }
-  if (invalid_nonstatic_memfn_p (exp, complain))
+  if (invalid_nonstatic_memfn_p (loc, exp, complain))
     return error_mark_node;
   if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
     return cp_build_addr_expr (exp, complain);
Index: testsuite/g++.dg/cpp0x/pr66130.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr66130.C    (revision 0)
+++ testsuite/g++.dg/cpp0x/pr66130.C    (working copy)
@@ -0,0 +1,11 @@
+// PR c++/66130
+// { dg-do compile { target c++11 } }
+
+struct Local
+{
+  void f();
+};
+
+Local *l;
+void (Local::*ptr)();
+decltype((l->*ptr)) i;  // { dg-error "member function of type 'void 
\\(Local::\\)\\(\\)'" }
Index: testsuite/g++.dg/other/pr66130.C
===================================================================
--- testsuite/g++.dg/other/pr66130.C    (revision 0)
+++ testsuite/g++.dg/other/pr66130.C    (working copy)
@@ -0,0 +1,11 @@
+// PR c++/66130
+
+struct X {
+  X(void *);
+  void m();  // { dg-message "declared here" }
+};
+
+struct Y : public X{
+  Y(void*a, void *b) : X(m), mb(b) { }  // { dg-error "member function 'void 
X::m\\(\\)'" }
+  void *mb;
+};

Reply via email to