https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95222
Bug ID: 95222 Summary: GCC 10.1 x86 issue with function pointers with calling convention attribute and template specialization Product: gcc Version: 10.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: raptorfactor at raptorfactor dot com Target Milestone: --- The following code (which is a simplified repro from a much larger function introspection library) used to work with GCC 9.x, but does not with the update to 10.1. Is this a compiler/toolchain bug or is there something incorrect about the code that I'm missing (obviously it's non-standard and relying on the behavior of vendor extensions)? >>>>>>>>>>>>>>> #if defined(_MSC_VER) #define CC_FASTCALL __fastcall #define CC_STDCALL __stdcall #else #define CC_FASTCALL __attribute__((fastcall)) #define CC_STDCALL __attribute__((stdcall)) #endif template <typename FuncT> struct FuncResult; template <typename R, typename... Args> struct FuncResult<R(*)(Args...)> { using type = R; }; template <typename R, typename... Args> struct FuncResult<R(CC_FASTCALL*)(Args...)> { using type = R; }; template <typename R, typename... Args> struct FuncResult<R(CC_STDCALL*)(Args...)> { using type = R; }; template <typename FuncT> auto wrap(FuncT f) -> typename FuncResult<FuncT>::type { return f(1, 2, 3); } int CC_FASTCALL func1(int x, int y, int z) { return x + y + z; } int CC_STDCALL func2(int x, int y, int z) { return x + y + z; } int main() { return wrap(&func1) + wrap(&func2); } >>>>>>>>>>>>>>> With the calling convention specific specialization: >>>>>>>>>>>>>>> main.cpp:19:8: error: redefinition of 'struct FuncResult<R (*)(Args ...)>' 19 | struct FuncResult<R(CC_FASTCALL*)(Args...)> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ main.cpp:13:8: note: previous definition of 'struct FuncResult<R (*)(Args ...)>' 13 | struct FuncResult<R(*)(Args...)> | ^~~~~~~~~~~~~~~~~~~~~~~~~ >>>>>>>>>>>>>>> Without the calling convention specific specialization: >>>>>>>>>>>>>>> main.cpp:50:23: error: no matching function for call to 'wrap(int (__attribute__((fastcall)) *)(int, int, int))' 50 | return wrap(&func1) + wrap(&func2); | ^ main.cpp:33:6: note: candidate: 'template<class FuncT> typename FuncResult<FuncT>::type wrap(FuncT)' 33 | auto wrap(FuncT f) -> typename FuncResult<FuncT>::type | ^~~~ main.cpp:33:6: note: template argument deduction/substitution failed: main.cpp: In substitution of 'template<class FuncT> typename FuncResult<FuncT>::type wrap(FuncT) [with FuncT = int (__attribute__((fastcall)) *)(int, int, int)]': main.cpp:50:23: required from here main.cpp:33:6: error: invalid use of incomplete type 'struct FuncResult<int (__attribute__((fastcall)) *)(int, int, int)>' main.cpp:10:8: note: declaration of 'struct FuncResult<int (__attribute__((fastcall)) *)(int, int, int)>' 10 | struct FuncResult; | ^~~~~~~~~~ >>>>>>>>>>>>>>> Damned if you do, damned if you don't. Is anyone aware of a workaround for this? It's blocking my build and I can't figure out an easy workaround. Thanks.