On 09/28/2017 05:23 AM, Pedro Alves wrote:
On 09/25/2017 02:03 AM, Martin Sebor wrote:

+a @option{-Wincompatible-pointer-types} warning for mismatches.  To suppress
+a warning for the necessary cast from a pointer to the implementation member
+function to the type of the corresponding non-member function use the
+@option{-Wno-pmf-conversions} option.  For example:

FWIW, it seems odd to me to tell users they need to suppress warnings, when
the compiler surely could provide better/safer means to avoid needing
to use the reinterpret_cast hammer.   See below.

+
+@smallexample
+class S
+@{
+private:
+  int debug_impl (int);
+  int optimized_impl (int);
+
+  typedef int Func (S*, int);
+
+  static Func* resolver ();
+public:
+
+  int interface (int);
+@};
+
+int S::debug_impl (int) @{ /* @r{@dots{}} */ @}
+int S::optimized_impl (int) @{ /* @r{@dots{}} */ @}
+
+S::Func* S::resolver ()
+@{
+  int (S::*pimpl) (int)
+    = getenv ("DEBUG") ? &S::debug_impl : &S::optimized_impl;
+
+  // Cast triggers -Wno-pmf-conversions.
+  return reinterpret_cast<Func*>(pimpl);
+@}
+

If I were writing code like this, I'd write a reinterpret_cast-like
function specifically for pointer-to-member-function to free-function
casting, and only suppress the warning there instead of disabling
the warning for the whole translation unit.  Something like:

#include <type_traits>

template<typename T> struct pmf_as_func;

template<typename Ret, typename S, typename... Args>
struct pmf_as_func<Ret (S::*) (Args...)>
{
  typedef Ret (func_type) (S *, Args...);
  typedef S struct_type;
};

template<typename Pmf>
typename pmf_as_func<Pmf>::func_type *
pmf_as_func_cast (Pmf pmf)
{
  static_assert (!std::is_polymorphic<typename 
pmf_as_func<Pmf>::struct_type>::value,
                 "");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpmf-conversions"
  return reinterpret_cast<typename pmf_as_func<Pmf>::func_type *> (pmf);
#pragma GCC diagnostic pop
}


and then write:
 return pmf_as_func_cast (pimpl);

instead of:
  return reinterpret_cast<Func*>(pimpl);

The point being of course to make it harder to misuse the casts.

But that may be a bit too much for the manual.

Yes, that's a much nicer solution but as you say, more code than
the manual typically includes for warnings.  (It would be a good
example for a Users Guide if GCC had one.)

It also wouldn't work as is with C++03 (because variatic templates).
Which leads me to think that if GCC guarantees this cast works, then
it'd be nice to have GCC provide it (like a __pmf_as_func_cast function)
as builtin.  Then it'd work on C++03 as well, and the compiler of course
can precisely validate whether the cast is valid.  (It's quite possible
that there's a better check than is_polymorphic as I've written above.)

I also don't like the cast and have been thinking about how to
suppress the warning in this case (the ifunc resolver).  But
the only way I can think to make it possible is to defer
-Wno-pmf-conversions until after all function declarations in
the translation unit have been processed.  In other words, run
it in a separate pass and suppress it for functions that have
been aliased via attribute ifunc.  I don't know if there already
is a pass like that it could be hooked into.  If there is, it
should be feasible.

Nathan or Jason, is there something like this?

Martin

Reply via email to