Files
sousa-gecko/build/clang-plugin/tests/TestFinalCycleCollectingIsupports.cpp
T
Keith Cirkel 2f1f3b0163 Bug 2045044 - Introduce clang plugin to check for using _FINAL macro variants for isupports r=dom-core-reviewers,firefox-static-analysis-reviewers,smaug,sergesanspaille
This change introduces a clang plugin which checks for uses of
`NS_DECL_CYCLE_COLLECTING_ISUPPORTS` in a `final` class. These should instead
use `NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL`.

Not using the `_FINAL` variant can slip in under code review, and still build,
but depending on how the unified builds work out might cause a build error. This
can result in someone making changes to e.g. moz.build having to do some wildly
unrelated follow up working cleaning these up before their build passes.

By introducing a clang plugin to catch these, we can prevent them entering into
tree, and hopefully have a happier and healthier codebase for it.

Differential Revision: https://phabricator.services.mozilla.com/D304799
2026-06-10 14:57:34 +00:00

46 lines
1.8 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Fake the path so the checker's directory allowlist matches.
#line 6 "/dom/html/TestFinalCycleCollectingIsupports.cpp"
// Minimal stubs matching the real macro structure in nsISupportsImpl.h.
// NS_DECL_CYCLE_COLLECTING_ISUPPORTS_META is the inner macro that emits
// `override` vs `final`; the checker inspects its name on the expansion stack.
#define NS_DECL_CYCLE_COLLECTING_ISUPPORTS_META(...) \
virtual void AddRef() __VA_ARGS__; \
virtual void Release() __VA_ARGS__;
#define NS_DECL_CYCLE_COLLECTING_ISUPPORTS \
NS_DECL_CYCLE_COLLECTING_ISUPPORTS_META(override)
#define NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL \
NS_DECL_CYCLE_COLLECTING_ISUPPORTS_META(final)
struct Base {
virtual void AddRef() = 0;
virtual void Release() = 0;
};
// Should error: final class using the non-final macro.
struct BadFinal final : Base { // expected-error {{final class 'BadFinal' uses NS_DECL_CYCLE_COLLECTING_ISUPPORTS; use NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL instead}}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS // expected-note {{replace NS_DECL_CYCLE_COLLECTING_ISUPPORTS with NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL}}
};
// Should not error: final class already using the final macro.
struct GoodFinal final : Base {
NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL
};
// Should not error: non-final class using the non-final macro.
struct GoodNonFinal : Base {
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
};
// Should not error: final class with manually-written override (not via macro).
struct ManualOverride final : Base {
virtual void AddRef() override;
virtual void Release() override;
};