[cfe-dev] Clang emits unreachable `internal linkage` constructor
Mehdi Amini via cfe-dev
cfe-dev at lists.llvm.org
Thu Oct 13 22:46:04 PDT 2016
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?)
- Have the CGSCC run on the unreachable part of the call-graph.
- Run global-DCE at O0 (might be a good idea anyway if it speeds-up the build)
- 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.
- We could make the basic_string constructor and other method in the same situation internal linkage instead.
Thoughts?
—
Mehdi
More information about the cfe-dev
mailing list