[cfe-dev] Clang emits unreachable `internal linkage` constructor

Richard Smith via cfe-dev cfe-dev at lists.llvm.org
Wed Oct 19 18:53:38 PDT 2016


On Tue, Oct 18, 2016 at 8:37 AM, Duncan P. N. Exon Smith via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

>
> > On 2016-Oct-13, at 22:46, Mehdi Amini via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
> >
> > Hi,
> >
> > This fairly simple (and valid) code does not link (on MacOS):
> >
> >
> > #include <iostream>
> > #include <string>
> > namespace {
> >       struct VA {
> >       };
> >       struct A : virtual public VA {
> >               A() {
> >                       static bool b = false;
> >                       std::string str;
> >               }
> >       };
> > }
> > int main(int argc, char* argv[]) {
> >       A::A a;
> > }
> >
> >
> >
> > The issue is that clang emits two constructors (the complete one and the
> base one) for struct A because it has a virtual base class.
> >
> > Because struct A is declared in an anonymous namespace, these
> constructors are internal linkage. Only one of them is actually called, the
> other is unreachable.
> >
> > The “always-inliner” does not visit unreachable internal function.
> However this constructor is calling into a function from libc++ that are
> marked “available_externally” and “always inline”: the basic_string
> constructor.
> >
> > The problem is that the linkage “available_externally" is a “lie”: there
> is an external template instantiation in the header, but it is marked
> “visibility hidden”. So the function cannot be linked to in the libc++
> dylib. (I think it’d work with a static libc++).
> >
> > I see multiple ways to address such cases, possibly many of them can be
> implemented:
> >
> > - Don’t emit unreferenced internal_linkage function. (We should try to
> do this anyway right?)
>
> This makes sense to me.  It seems to me like a bug that it's emitted.


Regardless, resolving it does not fix the problem here. For instance, the
same issue would arise under -femit-all-decls, or if uses exist at the AST
level but are optimized away after IR generation.

> - Have the CGSCC run on the unreachable part of the call-graph.
>
> This seems to pessimize the normal case.


Nonetheless, it's necessary if we want to provide the guarantee that the
always_inline attribute is supposed to provide. (It's not a hint; per the
GCC documentation it is an error if a function is annotated always_inline
and is not inlined.)

If we don't want to provide that guarantee, so be it, but then libc++'s use
of this attribute is simply wrong, since it's relying on that guarantee.

> - Run global-DCE at O0 (might be a good idea anyway if it speeds-up the
> build)
>
> Would we be surprised by anything it deletes?  If it's only going to
> delete unreferenced static globals, it seems (1) harmless and (2)
> unnecessary unless there are frontend bugs.  But maybe it's
>
> > - We should have the “available_externally” compatible with “hidden
> visibility”. Maybe we need a way to have to mark some method excluded from
> one  `external template` instantiation so that it would be ODR.
>
> This seems useful.  I think individual functions should be able to opt-out
> of a class-wide `extern template` instantiation.
>
> > - We could make the basic_string constructor and other method in the
> same situation internal linkage instead.
>
> Could pointer equality fail on the function pointers of
> basic_string::basic_string?
>
> >
> >
> > Thoughts?
> >
> > —
> > Mehdi
> > _______________________________________________
> > cfe-dev mailing list
> > cfe-dev at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20161019/3f7e2c98/attachment.html>


More information about the cfe-dev mailing list