10

A hole in Clang's `-Wsuggest-override` – Arthur O'Dwyer – Stuff mostly about C++

 4 years ago
source link: https://quuxplusone.github.io/blog/2021/02/19/virtual-final-silences-override-warning/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

A hole in Clang’s -Wsuggest-override

Consider 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 override or final (without virtual) 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!

-Wall includes -Winconsistent-missing-override, which warns within classes that are already using override in some places but not others. -Wsuggest-override is more advanced; it diagnoses missing override keywords 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:


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK