A hole in Clang’s -Wsuggest-override
-Wsuggest-overrideConsider this code (Godbolt):
struct B {
virtual int f() = 0;
virtual int g() = 0;
};
struct C : B {
int f() override;
virtual int g() final; // overrides
virtual int h() final; // doesn't
};
In any real codebase, you should never ever use virtual and final together like this.
Use only
virtual(preferably with=0) in root classes.Use only
overrideorfinal(withoutvirtual) in non-root classes.
So this code is extremely unrealistic.
However, I was surprised that Clang’s -Wsuggest-override diagnostic is not
smart enough to complain here. The syntax of this code fails to indicate its meaning —
obviously, because C::g() and C::h() have the same syntax but different meanings.
Therefore, the compiler really ought to discourage the programmer from writing
this “ambiguous” syntax.
By the way, kudos to Clang for implementing -Wsuggest-override at all.
I recommend that everybody turn it on immediately!
-Wallincludes-Winconsistent-missing-override, which warns within classes that are already usingoverridein some places but not others.-Wsuggest-overrideis more advanced; it diagnoses missingoverridekeywords even in classes that don’t already use it.
I think I want a diagnostic spelled something like -Wsuggest-omit-virtual.
Stylistically, the virtual keyword should be used only on roots; the absence of virtual
unambiguously signals the intentional absence of root-ness, in the same way that
the absence of override/final (in modern code) unambiguously signals
the intentional absence of overriding-ness.
The proper shape of class C is thus:
struct C : B {
int f() override;
int g() final; // overrides
virtual int h() final; // doesn't
};
g’s syntax now differs from h’s, which is appropriate, because g’s meaning
differs from h’s.
The use of virtual and final together in h’s signature indicates that
h is both a root and a leaf — highly unrealistic, but technically possible!
See also:
- “Two musings on the design of compiler warnings” (2020-09-02)
