Currently, in case two signals have the same signature (such as the StateMachine::stepped() templated signal or Ui::UserInterface::inputWidgetFocused() and inputWidgetBlurred() pair of signals, MSVC merges them in Release mode when the /OPT:ICF flag is enabled as their codegen is the same. That's very unfortunate and leads to nasty hard-to-prevent bugs.
Presently, there are the following options, none of which is ideal:
- Manually make each signal generate a different codegen by writing a different value to an internal member. That's how it's done now, is eww and doable only in library code -- we can't force the users to do the same with their emitter implementations.
- Globally enable
/OPT:NOICF. That'll prevent some useful optimizations elsewhere and again needs to be done by the users as CMake < 3.13 doesn't support INTERFACE_LINK_OPTIONS. Even with CMake 3.13, users with custom buildsystems will have issues because this flag won't get enabled for them automatically. (Note: it might be useful to say /OPT:REF,NOICF instead (source).)
- Work around this issue by changing the
emit() API. One idea I have is to replace it with a CORRADE_EMIT() macro that has __COUNTER__ inside, which then will get saved to an internal member of the Emitter class. This won't solve it for templated signals, though -- the user would again need to create a unique numeric identifier for these (typeid? something?).
- Maybe we can trick the optimizer into thinking the functions are different. Maybe sneaking a
printf() inside emit() would work? Some inline assembly?
- Maybe some special attributes could cause the function to not be affected by this optimization? (I couldn't find any.)
- Hope MSVC fixes this in the linker somehow (they know about it). Though that might not ever happen and even after that we need to stay compatible with previous releases.
In total, there are the following Windows-specific issues:
Currently, in case two signals have the same signature (such as the StateMachine::stepped() templated signal or Ui::UserInterface::inputWidgetFocused() and
inputWidgetBlurred()pair of signals, MSVC merges them in Release mode when the/OPT:ICFflag is enabled as their codegen is the same. That's very unfortunate and leads to nasty hard-to-prevent bugs.Presently, there are the following options, none of which is ideal:
/OPT:NOICF. That'll prevent some useful optimizations elsewhere and again needs to be done by the users as CMake < 3.13 doesn't support INTERFACE_LINK_OPTIONS. Even with CMake 3.13, users with custom buildsystems will have issues because this flag won't get enabled for them automatically. (Note: it might be useful to say/OPT:REF,NOICFinstead (source).)emit()API. One idea I have is to replace it with aCORRADE_EMIT()macro that has__COUNTER__inside, which then will get saved to an internal member of the Emitter class. This won't solve it for templated signals, though -- the user would again need to create a unique numeric identifier for these (typeid? something?).printf()insideemit()would work? Some inline assembly?In total, there are the following Windows-specific issues:
/OPT:ICFissuevirtual(might help casting the signal pointer to an unknown type to expand it to its full size)Signal with multiple inheritance don't seem to work at all on MinGW, even with thecan't reproducevirtualworkaround