Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visibility of inline template functions

What is the rational behind the fact that compiling

namespace ns __attribute__((visibility("default"))) {

template<typename T>
inline int func1(const T& x) {
    return x;
}

inline int func2(int x) {
    return x;
}

struct test {
    template<typename T>
    int func3(const T &x) { return x; }

    int func4(int x) { return x; }
};

}

int __attribute__((visibility("default"))) client(int x) {
    ns::test t;
    const int y1 = ns::func1(x);
    const int y2 = ns::func2(x);
    const int y3 = t.func3(x);
    const int y4 = t.func4(x);
    return y1 + y2 + y3 + y4;
}

with

g++ -Wall -fPIC \
    -fvisibility=hidden -fvisibility-inlines-hidden \
    -shared -o libtest.so test.cpp

yields a library exporting ns::test::func1<int>() and ns::test::func3<int>() but not ns::func2() nor ns::test::func4()? Both template functions are defined inline and -fvisibility-inlines-hidden tells the compiler to hide them — or at least their instantiations which hopefully are inline too.

Hiding the function templates func1 and func3 explicitly, i.e. with

 template<typename T>
 int __attribute__((visibility("hidden"))) func(const T &x) { return x; }

leads to the expected behavior. Omitting the default visibility in the namespace definition hides the two instantiations.

Background: We try to minimize the amount of visible symbols in our library. Thus we're using the mentioned compiler flags and attributes. Of course this is also necessary for all static third party libraries. But unfortunately those inline template functions inside included header files are completely out of our control. For example, every instantiation of

namespace std {

template<typename _CharT, typename _Traits, typename _Alloc>
inline bool
operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    const _CharT* __rhs)
{ return __lhs.compare(__rhs) == 0; }

}

from #include <string> will happily generate a publicly visible symbol inside my library. And the most annoying part, it will be put inside my library without any version information, so no GLIBCXX_3.x.z to differentiate.

Bonus Question: What's the overall impact using a linker script like

{
    global:
        _Z6clienti;
    local:
        *;
};

As far as I understand, this is only really feasible, if I don't use any exception handling nor dynamic type casting across the boundaries of my library. But what happens with those inline functions? It feels like this whole hidden visibility thing violates the one definition rule anyway, thus it's not a big deal.

like image 848
phlipsy Avatar asked Sep 06 '18 11:09

phlipsy


People also ask

Can you inline a template function?

Explicit instantiation of a function template or of a member function of a class template cannot use inline or constexpr .

What are the restriction of inline function?

Limitations of Inline FunctionsInline functions do not work if the body of the function contains any sort of looping or iteration. Inline functions do not support the use of switch or goto statements. C++ Inline functions cannot work if the function defined is recursive in nature.

What are advantages of making function inline?

Inline functions provide following advantages: 1) Function call overhead doesn't occur. 2) It also saves the overhead of push/pop variables on the stack when function is called. 3) It also saves overhead of a return call from a function.

Do inline functions affect the performance?

inline functions might make the code faster, they might make it slower. They might make the executable larger, they might make it smaller. They might cause thrashing, they might prevent thrashing. And they might be, and often are, totally irrelevant to speed.


1 Answers

GCC did not respect -fvisibility-inlines-hidden for template functions; it was a bug that was fixed starting from gcc-10.

With GCC 10, all four functions have hidden visibility (command line flag takes precedence over visibility attribute specified on the enclosing namespace).

like image 162
amonakov Avatar answered Oct 09 '22 16:10

amonakov