GCC Warns About Function Pointer to Object Pointer Cast

2.9k Views Asked by At

Clearly casting between function pointers and object pointers is undefined behaviour in the general sense, but POSIX (see: dlsym) and WinAPI (see: GetProcAddress) require this.

Given this, and given the fact that such code is targeting a platform-specific API anyway, its portability to platforms where function pointers and object pointers aren't compatible is really irrelevant.

But -Wpedantic warns about it anyway, and #pragma GCC diagnostic ignored "-Wpedantic" has no effect:

warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default]

I want to keep -Wpedantic enabled, since it does give good warnings, but I don't want to have real warnings and errors lost amidst a sea of irrelevant warnings about function pointer to object pointer casts.

Is there a way to accomplish this?

Running GCC 4.8.0 on Windows (MinGW):

gcc (rubenvb-4.8.0) 4.8.0

CODE SAMPLE

#include <windows.h>
#include <iostream>


int main (void) {

    std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),"five")) << std::endl;

}

Emits (with -Wpedantic):

warning_demo.cpp: In function 'int main()':
warning_demo.cpp:7:87: warning: ISO C++ forbids casting between pointer-to-funct
ion and pointer-to-object [enabled by default]
  std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),
"five")) << std::endl;

       ^
3

There are 3 best solutions below

1
On BEST ANSWER

I think you could use g++'s system_header directive here:

wrap_GetProcAddress.h:

#ifndef wrap_GetProcAddress_included
#define wrap_GetProcAddress_included

#pragma GCC system_header

template <typename Result>
Result GetProcAddressAs( [normal parameters] )
{
    return reinterpret_cast<Result>(GetProcAddressAs( [normal parameters] ));
}

#endif
3
On

There's always the memcpy trick you can use:

int (*f)() = 0;
int *o;
memcpy(&o, &f, sizeof(int*));

You can see it on ideone: m is generating warnings, while g is OK.

As to other course of action you might want to take: One obvious possibility would be to "fix" the header defining dlsym to actually return a function pointer (like void (*)()). Good luck with that.

1
On

This works fine.

template <typename RESULT, typename ...ARGS>
void * make_void_ptr(RESULT (*p)(ARGS...)) {
    static_assert(sizeof(void *) == sizeof(void (*)(void)),
                  "object pointer and function pointer sizes must equal");
    void *q = &p;
    return *static_cast<void **>(q);
}