-
Couldn't load subscription status.
- Fork 547
Use private virtual key_function() to address -Wweak-vtables
#1487
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively: Do we actually care about the weak-vtables warning? AFAIK, all modern linkers do comdat merging up-front, and a single instance of a single class across a few files feels unlikely to have a large build performance impact.
I do not have any emperical numbers concerning its effect on our codebase. However, per the linked Itanium ABI spec (our dtors are not pure virtual, but this recommendation highlights the fact that a virtual dtor is acceptable to use as the key function):
and per LLVM Coding Standards:
and per lld documentation:
I cannot find many references or materials regarding vtables, COMDAT groups, and their effect on linker performance. We could add as a third proposal to ignore/disable the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid Ro5 boilerplate and out-of-line defaulted virtual destructors. (Accept this PR.)
Avoid ABI-stability-supporting a "useless" function in the vtable. (Reject this PR.)
I am slightly in favor of rejecting this PR. Adding Ro5 boilerplate seems like a small development cost. And adding a "useless" vtable function seems like a small runtime cost. Between the two, I'd rather have the small development cost.
That said, this is mostly new to me (and the references are appreciated).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be in favor of accepting the PR, with a code comment explaining the purpose of key_function. I don't think there will be a potential runtime cost to have key_function, but the Ro5 simplification may be worth having.
Alternatively, if it is decided to reject this PR: There should be a comment on the purpose of the out-of-line definition of ~exception().
To clarify, this would be a small runtime memory cost (+1 vtable entry), but not a runtime performance cost (on the contrary, due to the inline dtor, we might see a minor performance improvement for non-LTO builds). According to this article (Feb 2023), the memory footprint of an additional vtable entry (for
Using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the near negligible memory impact, no objections.
Followup to #1469 per #1469 (comment).
Note
This PR explores an alternative design proposal. Rejecting this proposal is an acceptable outcome.
For polymorphic classes with no out-of-line virtual function available to act as the key function for the class' vtable, this PR proposes using a dedicated private and not-exported virtual function named
key_function()instead.This pattern avoids Ro5 boilerplate and avoids exporting virtual destructors in the stable ABI. However, this pattern comes at the cost of increasing the size of the vtable with an otherwise-useless function and locking-in the
key_function()into the stable ABI: even if the function itself is not exported, the function is part of the vtable, and the vtable is part of the stable ABI, sokey_function()is part of the stable ABI by transitivity (removal == ABI breaking change).Which of the following options do we prefer?