#include <stdio.h> struct A { template <typename T> static inline __attribute__((always_inline)) void Caller (T* pn, void (T::*pm)(void)) { (pn->*pm)(); } void Call (int i) { if (i == 1) Caller(this, &A::Func1); else if (i == 2) Caller(this, &A::Func2); } inline void Func1 (void) { puts ("Func1"); } inline void Func2 (void) noexcept { puts ("Func2"); } }; int main (void) { A a; a.Call(1); a.Call(2); return (0); } ------------------------------------------------------------- Compiling with: g++ (GCC) 4.7.0 20120324 (prerelease), x86_64 > g++ -O -std=c++11 a.cc a.cc: In function 'int main()': a.cc:5:55: error: inlining failed in call to always_inline 'static void A::Caller(T*, void (T::*)()) [with T = A]': mismatched arguments a.cc:10:42: error: called from here a.cc:5:55: error: inlining failed in call to always_inline 'static void A::Caller(T*, void (T::*)()) [with T = A]': mismatched arguments a.cc:10:42: error: called from here ------------------------------------------------------------- I'm using always_inline to force the error; without it Caller is not inlined errorlessly. The problem occurs when the function pointer has an inexact signature match to the pointed function. In the above example, Func2 has a noexcept tacked on to it. In more complex examples involving pointer to function with arguments, using a typedef of an object in argument list results in this error, while using the actual object works (typedef A a_t; void good(A&); void bad(a_t&)). So the compiler is able to explicitly convert an inexact match like &A::Func2 to void(A::*)(void) when instantiating the template, but the inliner is not able to make the same match even though it should have the same information.
It's the pointer-to-member function descriptor that is rejected. The compatibility check is too constrained, I have a fix (for this particular case at least).
Author: rguenth Date: Tue Apr 10 13:20:50 2012 New Revision: 186276 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=186276 Log: 2012-04-10 Richard Guenther <rguenther@suse.de> PR middle-end/52888 * gimple-low.c (gimple_check_call_args): Properly account for compatible aggregate types. Modified: trunk/gcc/ChangeLog trunk/gcc/gimple-low.c
Fixed for trunk.
*** Bug 55788 has been marked as a duplicate of this bug. ***
Author: rguenth Date: Fri Mar 1 12:46:12 2013 New Revision: 196378 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=196378 Log: 2013-03-01 Richard Biener <rguenther@suse.de> Backport from mainline 2012-04-10 Richard Guenther <rguenther@suse.de> PR middle-end/52888 * gimple-low.c (gimple_check_call_args): Properly account for compatible aggregate types. Modified: branches/gcc-4_7-branch/gcc/ChangeLog branches/gcc-4_7-branch/gcc/gimple-low.c
Fixed for 4.7.3, too.