Search code examples
c++macoslinkerclang++dead-code

Clang removing dead code incorrectly


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?


Solution

  • 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.