[cfe-dev] Adding a new attribute: no_extern_template

Reid Kleckner via cfe-dev cfe-dev at lists.llvm.org
Tue Aug 21 15:48:30 PDT 2018


On Tue, Aug 21, 2018 at 2:44 PM Louis Dionne via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> I've been looking to add an attribute (tentatively called
> no_extern_template) which would prevent member functions in a template from
> getting available_externally linkage even when there is a matching extern
> template declaration. In other words, given the following code:
>

The entire point of extern template declarations is to be able to emit
member functions with available_externally linkage, so this seems like a
pretty strange feature.

Is the original problem limited to the __init pattern (below), or are is
needed for more than that?
    template <class T>
    struct Foo {
        inline __attribute__((visibility("hidden")))
        int __init(int x) { /* LOTS OF CODE */ }

        inline __attribute__((visibility("default")))
        int bar(int x) { return __init(x); }
    };

My first idea (probably too simple to work and already rejected) is to mark
bar noinline. Then it will be available_externally, but not inlineable.
After CodeGen, we will have a call to the bar definition provided by the
libc++ DSO, and there will not be link errors. If that doesn't work, read
on.

We had a very similar to a problem with dllimport, which also uses
available_externally. This is the situation:

#if BUILDING_FOO
#define FOO_EXPORT __declspec(dllexport)
#else
#define FOO_EXPORT __declspec(dllimport)
#endif
struct Foo {
  void bar();
  void FOO_EXPORT foo() { bar(); }
};

When compiling the code that uses Foo, BUILDING_FOO is not defined, and
dllimport is used. However, Foo::foo calls Foo::bar, which is not exported,
and so the link will fail if foo() is emitted available_externally and
inlined. In this case, we found that we couldn't actually emit
available_externally definitions of foo, we just had to call the
out-of-line version provided by the DLL. See the
class DLLImportFunctionVisitor in CodeGenModule.cpp that implements this.
It's not bulletproof, but it works well enough.

I think we might want to consider implementing the same kind of traversal
to check for visibility conflicts (a default visibility function calls a
hidden one) before emitting available_externally functions for an extern
template declaration.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20180821/263dc4eb/attachment.html>


More information about the cfe-dev mailing list