http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52888

             Bug #: 52888
           Summary: Unable to inline function pointer call with inexact
                    signature match
    Classification: Unclassified
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: minor
          Priority: P3
         Component: rtl-optimization
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: msha...@users.sourceforge.net


#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.

Reply via email to