-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Add unnecessary-virtual-specifier to -Wextra #138741
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
@llvm/pr-subscribers-libcxx @llvm/pr-subscribers-clang Author: Devon Loehr (DKLoehr) ChangesEffectively a reland of #133265, though due to discussion there we add the warning to -Wextra instead of turning it on by default. We still need to disable it for LLVM due to our unusual policy of using virtual From the previous PR: I've been working on cleaning up this warning in two codebases: LLVM and chromium (plus its dependencies). The chromium + dependency cleanup has been straightforward. Git archaeology shows that there are two reasons for the warnings: classes to which The LLVM cleanup was more surprising: I discovered that we have an old policy about including out-of-line virtual functions in every class with a vtable, even Overall, it seems like the warning is genuinely useful in most codebases (evidenced by chromium and its dependencies), and LLVM is an unusual case. Therefore we should enable the warning by default, and turn it off only for LLVM builds. Full diff: https://github.com/llvm/llvm-project/pull/138741.diff 1 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 1faf8508121f4..bb6e7070b1574 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -421,13 +421,12 @@ def CXX11WarnSuggestOverride : DiagGroup<"suggest-override">;
def WarnUnnecessaryVirtualSpecifier : DiagGroup<"unnecessary-virtual-specifier"> {
code Documentation = [{
Warns when a ``final`` class contains a virtual method (including virtual
-destructors). Since ``final`` classes cannot be subclassed, their methods
-cannot be overridden, and hence the ``virtual`` specifier is useless.
+destructors) that does not override anything. Since ``final`` classes cannot
+be subclassed, their methods cannot be overridden, so there is no point to
+introducing new ``virtual`` methods.
The warning also detects virtual methods in classes whose destructor is
``final``, for the same reason.
-
-The warning does not fire on virtual methods which are also marked ``override``.
}];
}
@@ -1163,6 +1162,7 @@ def Extra : DiagGroup<"extra", [
FUseLdPath,
CastFunctionTypeMismatch,
InitStringTooLongMissingNonString,
+ WarnUnnecessaryVirtualSpecifier,
]>;
def Most : DiagGroup<"most", [
|
@zmodem @AaronBallman @Sirraide -- reviewers from previous attempt @philnik777 -- do you think this PR will work with libc++? |
This should probably work. To make sure you can make a simple change in 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.
The LLVM cleanup was more surprising: I discovered that we have an old policy about including out-of-line virtual functions in every class with a vtable, even final ones. This means our codebase has many virtual "anchor" functions which do nothing except control where the vtable is emitted, and which trigger the warning. I looked into alternatives to satisfy the policy, such as using destructors instead of introducing a new function, but it wasn't clear if they had larger implications.
I wonder if we could add an escape hatch for this somehow—maybe don’t fire the warning on the first virtual function that is declared out-of-line if there’s an easy way of doing that, but that feels like a hack. We could also add an attribute instead to surpress the warning, but is adding an attribute for a single diagnostic really worth it?
Alternatively, we could ‘fix’ our codebase instead by introducing an LLVM_VIRTUAL_ANCHOR
macro or sth like that which disables the diagnostic for that one declaration—I guess this probably depends how common this pattern is elsewhere; if there are a lot of people who do this then the attribute might be easier to use.
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.
lgtm (without the libcxx/src/hash.cpp change obviously)
This reverts commit 56baa26.
Looks like all the libc++ checks passed, so we should be good.
This seems like a good way to do it, since it clearly documents what's going on. LLVM is the only project I've seen with such a policy; across all of chromium's dependencies, the extra |
Alright, in that case I’d say it would be nice to do that in a follow-up pr so we can stop disabling the warning. |
Effectively a reland of #133265, though due to discussion there we add the warning to -Wextra instead of turning it on by default. We still need to disable it for LLVM due to our unusual policy of using virtual
anchor
functions even in final classes. We now check if the warning exists before disabling it in LLVM builds, so hopefully this will fix the issues libcxx ran into last time.From the previous PR:
I've been working on cleaning up this warning in two codebases: LLVM and chromium (plus its dependencies). The chromium + dependency cleanup has been straightforward. Git archaeology shows that there are two reasons for the warnings: classes to which
final
was added after they were initially committed, and classes with virtual destructors that nobody remarks on. Presumably the latter case is because people are just very used to destructors being virtual.The LLVM cleanup was more surprising: I discovered that we have an old policy about including out-of-line virtual functions in every class with a vtable, even
final
ones. This means our codebase has many virtual "anchor" functions which do nothing except control where the vtable is emitted, and which trigger the warning. I looked into alternatives to satisfy the policy, such as using destructors instead of introducing a new function, but it wasn't clear if they had larger implications.Overall, it seems like the warning is genuinely useful in most codebases (evidenced by chromium and its dependencies), and LLVM is an unusual case. Therefore we should enable the warning by default, and turn it off only for LLVM builds.