Bug 52888 - Unable to inline function pointer call with inexact signature match
Summary: Unable to inline function pointer call with inexact signature match
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.7.0
: P3 minor
Target Milestone: 4.7.3
Assignee: Richard Biener
URL:
Keywords:
: 55788 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-04-06 16:08 UTC by Mike Sharov
Modified: 2013-03-01 13:09 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work: 4.7.3, 4.8.0
Known to fail: 4.7.2
Last reconfirmed: 2012-04-10 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Sharov 2012-04-06 16:08:59 UTC
#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.
Comment 1 Richard Biener 2012-04-10 11:49:14 UTC
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).
Comment 2 Richard Biener 2012-04-10 13:20:55 UTC
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
Comment 3 Richard Biener 2012-04-10 13:21:11 UTC
Fixed for trunk.
Comment 4 Richard Biener 2013-03-01 11:08:02 UTC
*** Bug 55788 has been marked as a duplicate of this bug. ***
Comment 5 Richard Biener 2013-03-01 12:46:17 UTC
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
Comment 6 Richard Biener 2013-03-01 13:09:58 UTC
Fixed for 4.7.3, too.