-
Notifications
You must be signed in to change notification settings - Fork 1.3k
RFC compile time check on signal callback signature #19818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
936cac1 to
f0c920c
Compare
|
Sounds like a nice project :) |
25412d2 to
e6f1ade
Compare
Of course when I started I thought this might be worth spending a few hours on... I would appreciate if you had a look at the code "style" changes in the first commit, since many more of these are needed to complete this. There would be some value in merging the second commit in disabled state so it can be enabled at will to check new code. But of course the real value only comes when the static assert is enabled (maybe only in Debug mode, since we have that running on CI). For that I could really use some help. Most of the changes are quite mechanical (just some basic understanding needed and a willingness to read the changes already made as examples). |
|
@dterrahe for me this seems to be another big round of important code maintenance work. I dont have a lot on my personal agenda and can't contribute to the gtk4 project (not knowing howto do that well). I could take this pr and continue your work if you would like me to do so you can concentrate on the gtk thing. Just let me know... |
Remove the G_OBJECT(wrapper) since it isn't necessary and hides the real type
void(*)() fails callback check; use void(*)(void)
e6f1ade to
c51ae98
Compare
|
Some progress and some blockers. The static compile time identification of the function signature (using _Generic) needs an exact match. So It might still be nice to make all the type conversions explicit over time and then maybe these fallbacks could/should be removed. Also, the macros involved are by now ridiculous in size, when expanded, It turns out that the static checking only works in llvm. gcc treats the const ints Anyway, this is a little premature, because the other issue that surfaced is that when a parameter in the signature is declared Sigh. OK, after all that I now realise that I could have achieved my original goal of identifying incorrect signal handler returns types with just this: This still (after all the fixes in the first commit) shows this |
Absolutely, this is just one run in the CI matrix to make sure we haven't broken the Debug build somehow. If it makes more sense to use another compiler here - why not. |
We sometimes find elusive bugs caused by signals being connected to handlers that don't provide the correct return value, i.e. void instead of gboolean. GTK/GObject don't have built-in signature checking when connecting signals, as this is not really natively supported in c. This PR adds such checking by extensively using the
_Genericconstruct. For this it is necessary to separately provide the expected handler signatures for each type of signal (see the second commit which adds this togtk.h). Since some signals expect different handlers depending on which type of object they are sent for, there is some loss of specificity, but for the common cases, for examplebutton-pressandclicked, this has already helped me find a couple of mismatches (that are now well-hidden in this rather large PR).It is common practice to send objects as
user_datathat are implicitly converted togpointerand then upon receipt in the handler explicitly converted back to the real type (obviously without any type checking happening). These now need to be declared as their real type in the handler prototype or they'll throw an error. Similarly, generic objects (like widgets) that get a signal connected are often declared as their real type (for example button) in the handler prototype. These implicit conversions now need to be made explicit (either when connecting or when receiving the signal).So for the moment many errors are generated. Until these are largely resolved, it is easier to ignore them at compile time (so the compile is allowed to finish) and only print them at runtime. With a decent IDE it is then faster to fix a number of them at the same time. Obviously this has the drawback that one actually has to activate all the
signal_connects (by opening all dialogs etc) otherwise the type mismatch will still be ignored.Eventually, when all existing mismatches are resolved, this can be made into a compile time fail (so that CI will also catch it) by uncommenting the
_Static_assert. All the checks are already done at compile time only and don't generate any code, except when an error needs to be printed.Obviously this PR is already rather large. Every signal_connect needs to be touched, because the unnecessary casts to G_OBJECT used to hide the real object type making it impossible to check for a signature with it as the first parameter in
_Generic. It may not be too useful to complete the whole exercise before GTK4, although getting rid of all the remaining false positives before the end of porting may help find real issues.