Author: Zeyi Xu Date: 2026-04-13T12:43:40Z New Revision: b9d6efebf9c6527c389868caa4dfcbdc0b8078a5
URL: https://github.com/llvm/llvm-project/commit/b9d6efebf9c6527c389868caa4dfcbdc0b8078a5 DIFF: https://github.com/llvm/llvm-project/commit/b9d6efebf9c6527c389868caa4dfcbdc0b8078a5.diff LOG: [clang-tidy] Emit warning when user is using deprecated `zircon` checks (#189522) Add `utils::diagDeprecatedCheckAlias` so checks can detect whether they are running under a deprecated name without enabling the new names. This commit also comes with an example with `zircon` module. It is deprecated in 22 release but we didn't provide a note for it before. Added: clang-tools-extra/clang-tidy/utils/CheckUtils.h clang-tools-extra/test/clang-tidy/checkers/fuchsia/temporary-objects-deprecated-alias.cpp Modified: clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.cpp clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.h clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.cpp index 3acd5fb555532..2fa83b41869ea 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "TemporaryObjectsCheck.h" +#include "../utils/CheckUtils.h" #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -19,6 +20,9 @@ namespace clang::tidy::fuchsia { namespace { +constexpr llvm::StringLiteral DeprecatedCheckName = "zircon-temporary-objects"; +constexpr llvm::StringLiteral CanonicalCheckName = "fuchsia-temporary-objects"; + AST_MATCHER_P(CXXRecordDecl, matchesAnyName, ArrayRef<StringRef>, Names) { const std::string QualifiedName = Node.getQualifiedNameAsString(); return llvm::is_contained(Names, QualifiedName); @@ -26,6 +30,15 @@ AST_MATCHER_P(CXXRecordDecl, matchesAnyName, ArrayRef<StringRef>, Names) { } // namespace +TemporaryObjectsCheck::TemporaryObjectsCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + Names(utils::options::parseStringList(Options.get("Names", ""))) { + if (Name == DeprecatedCheckName) + utils::diagDeprecatedCheckAlias(*this, *Context, DeprecatedCheckName, + CanonicalCheckName); +} + void TemporaryObjectsCheck::registerMatchers(MatchFinder *Finder) { // Matcher for default constructors. Finder->addMatcher( diff --git a/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.h b/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.h index 805dae4d577d8..74ab2a1be401c 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.h +++ b/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.h @@ -21,9 +21,7 @@ namespace clang::tidy::fuchsia { /// https://clang.llvm.org/extra/clang-tidy/checks/fuchsia/temporary-objects.html class TemporaryObjectsCheck : public ClangTidyCheck { public: - TemporaryObjectsCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), - Names(utils::options::parseStringList(Options.get("Names", ""))) {} + TemporaryObjectsCheck(StringRef Name, ClangTidyContext *Context); bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus; } diff --git a/clang-tools-extra/clang-tidy/utils/CheckUtils.h b/clang-tools-extra/clang-tidy/utils/CheckUtils.h new file mode 100644 index 0000000000000..af4821ea13520 --- /dev/null +++ b/clang-tools-extra/clang-tidy/utils/CheckUtils.h @@ -0,0 +1,26 @@ +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_CHECKUTILS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_CHECKUTILS_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::utils { + +/// Emits a configuration diagnostic when a deprecated check alias is enabled +/// and the canonical check name is not also enabled. +inline void diagDeprecatedCheckAlias(ClangTidyCheck &Check, + const ClangTidyContext &Context, + StringRef DeprecatedName, + StringRef CanonicalName) { + if (!Context.isCheckEnabled(DeprecatedName) || + Context.isCheckEnabled(CanonicalName)) + return; + + Check.configurationDiag( + "'%0' check is deprecated and will be removed in a future release; " + "consider using '%1' instead") + << DeprecatedName << CanonicalName; +} + +} // namespace clang::tidy::utils + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_CHECKUTILS_H diff --git a/clang-tools-extra/test/clang-tidy/checkers/fuchsia/temporary-objects-deprecated-alias.cpp b/clang-tools-extra/test/clang-tidy/checkers/fuchsia/temporary-objects-deprecated-alias.cpp new file mode 100644 index 0000000000000..301cae523bf4e --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/fuchsia/temporary-objects-deprecated-alias.cpp @@ -0,0 +1,18 @@ +// RUN: %check_clang_tidy %s zircon-temporary-objects %t -- \ +// RUN: -config="{CheckOptions: {zircon-temporary-objects.Names: 'Foo'}}" +// RUN: %check_clang_tidy -check-suffix=BOTH %s \ +// RUN: zircon-temporary-objects,fuchsia-temporary-objects %t -- \ +// RUN: -config="{CheckOptions: {zircon-temporary-objects.Names: 'Foo', \ +// RUN: fuchsia-temporary-objects.Names: 'Foo'}}" + +class Foo { +public: + Foo() = default; +}; + +void f() { + Foo(); + // CHECK-MESSAGES: warning: 'zircon-temporary-objects' check is deprecated and will be removed in a future release; consider using 'fuchsia-temporary-objects' instead [clang-tidy-config] + // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: creating a temporary object of type 'Foo' is prohibited [zircon-temporary-objects] + // CHECK-MESSAGES-BOTH: :[[@LINE-3]]:3: warning: creating a temporary object of type 'Foo' is prohibited +} diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp index aee3313f2263b..3f86f65c1ce65 100644 --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp @@ -1,6 +1,7 @@ #include "ClangTidyOptions.h" #include "ClangTidyCheck.h" #include "ClangTidyDiagnosticConsumer.h" +#include "utils/CheckUtils.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Testing/Annotations/Annotations.h" @@ -359,6 +360,123 @@ TEST(CheckOptionsValidation, MissingOptions) { EXPECT_TRUE(DiagConsumer.take().empty()); } +TEST(CheckOptionsValidation, DeprecatedAliasUtils) { + ClangTidyOptions Options; + Options.Checks = "performance-faster-string-find"; + + ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>( + ClangTidyGlobalOptions(), Options)); + ClangTidyDiagnosticConsumer DiagConsumer(Context); + auto DiagOpts = std::make_unique<DiagnosticOptions>(); + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, + false); + Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); + + TestCheck TestCheck(&Context); + utils::diagDeprecatedCheckAlias(TestCheck, Context, + "performance-faster-string-find", + "performance-prefer-single-char-overloads"); + + EXPECT_THAT( + DiagConsumer.take(), + ElementsAre( + AllOf(ToolDiagMessage( + "'performance-faster-string-find' check is deprecated and " + "will be removed in a future release; consider using " + "'performance-prefer-single-char-overloads' instead"), + ToolDiagLevel(Warning)))); +} + +TEST(CheckOptionsValidation, DeprecatedAliasUtilsDisabledByCanonicalCheck) { + ClangTidyOptions Options; + Options.Checks = + "performance-faster-string-find,performance-prefer-single-char-overloads"; + + ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>( + ClangTidyGlobalOptions(), Options)); + ClangTidyDiagnosticConsumer DiagConsumer(Context); + auto DiagOpts = std::make_unique<DiagnosticOptions>(); + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, + false); + Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); + + TestCheck TestCheck(&Context); + utils::diagDeprecatedCheckAlias(TestCheck, Context, + "performance-faster-string-find", + "performance-prefer-single-char-overloads"); + + EXPECT_TRUE(DiagConsumer.take().empty()); +} + +TEST(CheckOptionsValidation, DeprecatedAliasUtilsEnabledByWildcardAlias) { + ClangTidyOptions Options; + Options.Checks = "performance-faster*"; + + ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>( + ClangTidyGlobalOptions(), Options)); + ClangTidyDiagnosticConsumer DiagConsumer(Context); + auto DiagOpts = std::make_unique<DiagnosticOptions>(); + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, + false); + Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); + + TestCheck TestCheck(&Context); + utils::diagDeprecatedCheckAlias(TestCheck, Context, + "performance-faster-string-find", + "performance-prefer-single-char-overloads"); + + EXPECT_THAT( + DiagConsumer.take(), + ElementsAre( + AllOf(ToolDiagMessage( + "'performance-faster-string-find' check is deprecated and " + "will be removed in a future release; consider using " + "'performance-prefer-single-char-overloads' instead"), + ToolDiagLevel(Warning)))); +} + +TEST(CheckOptionsValidation, + DeprecatedAliasUtilsDisabledByWildcardAliasAndCanonicalCheck) { + ClangTidyOptions Options; + Options.Checks = + "performance-faster*,performance-prefer-single-char-overloads"; + + ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>( + ClangTidyGlobalOptions(), Options)); + ClangTidyDiagnosticConsumer DiagConsumer(Context); + auto DiagOpts = std::make_unique<DiagnosticOptions>(); + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, + false); + Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); + + TestCheck TestCheck(&Context); + utils::diagDeprecatedCheckAlias(TestCheck, Context, + "performance-faster-string-find", + "performance-prefer-single-char-overloads"); + + EXPECT_TRUE(DiagConsumer.take().empty()); +} + +TEST(CheckOptionsValidation, DeprecatedAliasUtilsDisabledByWildcard) { + ClangTidyOptions Options; + Options.Checks = "performance-*"; + + ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>( + ClangTidyGlobalOptions(), Options)); + ClangTidyDiagnosticConsumer DiagConsumer(Context); + auto DiagOpts = std::make_unique<DiagnosticOptions>(); + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, + false); + Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); + + TestCheck TestCheck(&Context); + utils::diagDeprecatedCheckAlias(TestCheck, Context, + "performance-faster-string-find", + "performance-prefer-single-char-overloads"); + + EXPECT_TRUE(DiagConsumer.take().empty()); +} + TEST(CheckOptionsValidation, ValidIntOptions) { ClangTidyOptions Options; auto &CheckOptions = Options.CheckOptions; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
