dllexport and inline methods

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I'm developing for Windows and recently started a project using
mingw (with gcc v4.7.2) - also tried mingw64 (with gcc v4.8.0).
I am getting some expected behaviour.  To cut to the chase:

testlib.hpp

    class __declspec(dllexport) A {
    public:
        int fa() { return m; }
        int ga();
    private:
        int m{0};
    };

    class __declspec(dllexport) B {
    public:
        int fb();
        int gb();
    private:
        int m{0};
    };
    inline int B::fb() { return m; }

    class C {
    public:
        int fc() { return m; }
        __declspec(dllexport) int gc();
    private:
        int m{0};
    };

testlib.cpp

    #include "test.hpp"
    int A::ga() { return (fa() + 1); }
    int B::gb() { return (fb() + 1); }
    int C::gc() { return (fc() + 1); }


(Obviously the dllexport attribute would normally be inside a
macro to switch back and forth between import and export as
needed.  But for clarity I've left it raw.)

Compile with options: -std=c++11 -O2 -S

The output for A::ga() looks like:
        subq    $40, %rsp
        .seh_stackalloc 40
        .seh_endprologue
        call    _ZN1A2faEv
        addl    $1, %eax
        addq    $40, %rsp
        ret

The output for B::gb() looks like:
        subq    $40, %rsp
        .seh_stackalloc 40
        .seh_endprologue
        call    _ZN1B2fbEv
        addl    $1, %eax
        addq    $40, %rsp
        ret

The output for C::gc() looks like:
        .seh_endprologue
        movl    (%rcx), %eax
        addl    $1, %eax
        ret

with -Winline on the command line we get these warnings:
warning: function 'int B::fb()' can never be inlined because it
         uses attributes conflicting with inlining [-Winline]
warning: inlining failed in call to 'int B::fb()': function not
         inlinable [-Winline] (called from B::gb())

There is no warning that A::fa() will not be inlined (though
I think this is probably expected).


Notice that inline methods for class A and class B are NOT
being inlined inside the library (and the compiler does tell us
why in the case of B::fb()).

Having spent a long time developing with msvc, this behaviour
is quite unexpected.  See discussion relating to msvc here:
http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx
(Also, I ran the same code (after adjusting the c++11
initialisation) through msvc v17.0 and can see that
all inline methods are being inlined.)

I've asked this question on stackoverflow and on mingw64 forum,
(I really wasn't sure where I should be trying to report this),
but the only "solution" so far is to go with what you see in
class C.  I can understand the arguments and discomfort that
people feel about class A and class B, especially when you read
about what is supposed to be possible with replacing the
implementation of exported functions, but consider also the
effects of requiring the class C style of declaration for all
shared library code.  (I had hoped that the gcc option:
-fvisibility-inlines-hidden might be applicable in this case,
but it makes no difference to the problems shown above.)

Take a look around at widely used code such as boost, Qt, ICU
and wxWidgets.  These all use class declarations similar to
class A and class B.  So in all these cases we can expect the
mingw/gcc builds of shared libraries for those products will
NOT inline the many simple accessor methods when used inside
the library (users of the library do get inlined).

Do I report this as a bug, or am I missing something?

-- 
Geoff Worboys
Telesis Computing Pty Ltd





[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux