I think this is a bug in clang
or the OSX linker, but I wanted to ask here to make sure.
I have the following (simplified) setup in a C++ program. A singleton Repository class:
class Repository {
public:
static Repository *instance();
void registerWidget(const char *name, Widget *w) {}
};
A widget interface:
class Widget {
public:
virtual void widgetify() = 0;
};
Finally a simple widget:
class SimpleWidget : public Widget {
public:
virtual void widgetify() {}
};
Inside SimpleWidget
I want to register the widget to the Repository
at run-time automagically. Normally I do this using an anonymous namespace and a register function. Something like this:
namespace {
bool registrar() {
Registrar::instance() -> registerWidget("SimpleWidget", new SimpleWidget);
return true;
}
bool R = registrar();
}
In a current project using Qt
targeting iOS and Android I've run into a problem with this system. clang
(or the linker) is identifying SimpleWidget
as dead code and stripping it (and thus it doesn't show up in Repository
since registrar()
is never called.) It seems to do this despite the fact that SimpleWidget
is obviously referenced in registrar()
. If I make a reference to SimpleWidget
in any of my other translation units, then SimpleWidget
is no longer stripped and everything works properly.
Am I missing something about how dead code stripping should work, or is this a legit tool chain bug?
All objects in a translation unit (such as R) need to be created before the first call to a function in that Translation Unit (.cpp file). You don't have a call to a single function in your TU, so R
does not need to be created, so registrar()
is indeed dead code, and anything called exclusively from registrar()
is equally dead.
The toolchain is correct.