https://github.com/earnol updated 
https://github.com/llvm/llvm-project/pull/197927

>From d9e868c8924e409d0207080007193710291ec0df Mon Sep 17 00:00:00 2001
From: Vladislav Aranov <[email protected]>
Date: Fri, 15 May 2026 00:38:26 +0200
Subject: [PATCH] [clang-tidy] Add checker alias framework and restore hicpp
 aliases

The change https://github.com/llvm/llvm-project/issues/183462 and subsequent
changes removed all hicpp checkers with giving little time to adapt.
This change adds a generic check alias mechanism to clang-tidy that supports:
registering aliases, central alias management table, bidirectional disable 
semantics,
NOLINT suppression using alias names, canonical name preference,
opt-in alias usage notification feature.
---
 clang-tools-extra/clang-tidy/CMakeLists.txt   |   9 +-
 clang-tools-extra/clang-tidy/ClangTidy.cpp    |   2 +
 .../ClangTidyDiagnosticConsumer.cpp           | 109 +++++++++++++++++-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h  |   7 ++
 .../clang-tidy/ClangTidyForceLinker.h         |   5 +
 .../clang-tidy/ClangTidyModule.cpp            |  14 ++-
 .../clang-tidy/ClangTidyModule.h              |  21 ++++
 .../clang-tidy/aliases/CMakeLists.txt         |  21 ++++
 .../clang-tidy/aliases/ClangTidyAliases.cpp   |  95 +++++++++++++++
 .../clang-tidy/aliases/ClangTidyAliases.h     |  57 +++++++++
 .../clang-tidy/cert/CERTTidyModule.cpp        |   5 -
 .../clang-tidy/tool/ClangTidyMain.cpp         |  18 +++
 clang-tools-extra/docs/ReleaseNotes.rst       |   7 ++
 clang-tools-extra/docs/clang-tidy/index.rst   |   3 +
 .../clang-tidy/checkers/cert/oop11-cpp.cpp    |   2 +-
 .../clang-tidy/checkers/check-aliasing.cpp    |  49 ++++++++
 16 files changed, 409 insertions(+), 15 deletions(-)
 create mode 100644 clang-tools-extra/clang-tidy/aliases/CMakeLists.txt
 create mode 100644 clang-tools-extra/clang-tidy/aliases/ClangTidyAliases.cpp
 create mode 100644 clang-tools-extra/clang-tidy/aliases/ClangTidyAliases.h
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/check-aliasing.cpp

diff --git a/clang-tools-extra/clang-tidy/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/CMakeLists.txt
index 9ee9255fbe17b..5d71355fc0c6e 100644
--- a/clang-tools-extra/clang-tidy/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/CMakeLists.txt
@@ -19,6 +19,9 @@ add_clang_library(clangTidy STATIC
   GlobList.cpp
   NoLintDirectiveHandler.cpp
 
+  LINK_LIBS
+  clangTidyAliasesModule
+
   DEPENDS
   ClangSACheckers
   omp_gen
@@ -50,8 +53,9 @@ endif()
 
 # Checks.
 # If you add a check, also add it to ClangTidyForceLinker.h in this directory.
-add_subdirectory(android)
 add_subdirectory(abseil)
+add_subdirectory(aliases)
+add_subdirectory(android)
 add_subdirectory(altera)
 add_subdirectory(boost)
 add_subdirectory(bugprone)
@@ -77,8 +81,9 @@ add_subdirectory(portability)
 add_subdirectory(readability)
 add_subdirectory(zircon)
 set(ALL_CLANG_TIDY_CHECKS
-  clangTidyAndroidModule
   clangTidyAbseilModule
+  clangTidyAliasesModule
+  clangTidyAndroidModule
   clangTidyAlteraModule
   clangTidyBoostModule
   clangTidyBugproneModule
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp 
b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index 05c8fd02fe86a..a8468a6e333d9 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -360,6 +360,7 @@ ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
     std::unique_ptr<ClangTidyModule> Module = E.instantiate();
     Module->addCheckFactories(*CheckFactories);
   }
+  CheckFactories->resolveAliases();
 }
 
 #if CLANG_TIDY_ENABLE_STATIC_ANALYZER
@@ -720,6 +721,7 @@ ChecksAndOptions getAllChecksAndOptions(bool 
AllowEnablingAnalyzerAlphaCheckers,
        ClangTidyModuleRegistry::entries()) {
     Module.instantiate()->addCheckFactories(Factories);
   }
+  Factories.resolveAliases();
 
   for (const auto &Factory : Factories)
     Result.Checks.insert(Factory.getKey());
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index 88d0a433bc7fb..c39c044be286a 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -19,6 +19,7 @@
 #include "ClangTidyOptions.h"
 #include "GlobList.h"
 #include "NoLintDirectiveHandler.h"
+#include "aliases/ClangTidyAliases.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/Attr.h"
@@ -27,6 +28,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Frontend/DiagnosticRenderer.h"
 #include "clang/Lex/Lexer.h"
@@ -34,9 +36,12 @@
 #include "clang/Tooling/Core/Replacement.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h" // IWYU pragma: keep
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Regex.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
 #include <optional>
 #include <tuple>
 #include <utility>
@@ -216,8 +221,23 @@ bool ClangTidyContext::shouldSuppressDiagnostic(
     SmallVectorImpl<tooling::Diagnostic> &NoLintErrors, bool AllowIO,
     bool EnableNoLintBlocks) {
   const std::string CheckName = getCheckName(Info.getID());
-  return NoLintHandler.shouldSuppress(DiagLevel, Info, CheckName, NoLintErrors,
-                                      AllowIO, EnableNoLintBlocks);
+  if (NoLintHandler.shouldSuppress(DiagLevel, Info, CheckName, NoLintErrors,
+                                   AllowIO, EnableNoLintBlocks))
+    return true;
+  // Also check if any alias name for this check is suppressed.
+  for (const StringRef Alias :
+       ClangTidyAliases::getAliasesForCanonical(CheckName)) {
+    if (NoLintHandler.shouldSuppress(DiagLevel, Info, std::string(Alias),
+                                     NoLintErrors, AllowIO,
+                                     EnableNoLintBlocks)) {
+      if (NotifyAliases)
+        llvm::errs() << "note: '" << Alias
+                     << "' is an alias for canonical name '" << CheckName
+                     << "' [checker-alias]\n";
+      return true;
+    }
+  }
+  return false;
 }
 
 void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) {
@@ -236,13 +256,90 @@ static bool 
parseFileExtensions(llvm::ArrayRef<std::string> AllFileExtensions,
   return true;
 }
 
+/// Expand check alias patterns in the checks string.
+/// For each glob pattern, if it matches an alias name, also add the canonical
+/// name (and vice versa) with the same +/- prefix. This ensures that disabling
+/// either name disables both.
+static std::string expandCheckAliases(StringRef Checks) {
+  if (Checks.empty())
+    return {};
+
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  bool First = true;
+
+  StringRef Remaining = Checks;
+  while (!Remaining.empty()) {
+    // Trim leading whitespace/commas.
+    Remaining = Remaining.ltrim(" \t\n");
+    if (Remaining.empty())
+      break;
+    if (Remaining.front() == ',') {
+      Remaining = Remaining.drop_front();
+      continue;
+    }
+
+    // Extract the prefix (- or nothing).
+    const bool IsNegative = Remaining.consume_front("-");
+    // Extract the glob text up to the next comma or newline.
+    const StringRef Glob =
+        Remaining.substr(0, Remaining.find_first_of(",\n")).trim();
+    Remaining = Remaining.substr(Glob.size());
+
+    if (Glob.empty())
+      continue;
+
+    // Write the original pattern.
+    if (!First)
+      OS << ',';
+    if (IsNegative)
+      OS << '-';
+    OS << Glob;
+    First = false;
+
+    // Check if this glob matches any alias or canonical name.
+    // Create a regex from the glob for matching.
+    SmallString<128> RegexText("^");
+    for (const char C : Glob) {
+      if (C == '*') {
+        RegexText.append(".*");
+      } else if (StringRef("()^$|+?.[]\\{}").contains(C)) {
+        RegexText.push_back('\\');
+        RegexText.push_back(C);
+      } else {
+        RegexText.push_back(C);
+      }
+    }
+    RegexText.push_back('$');
+    const llvm::Regex Re(RegexText);
+
+    for (const auto &Entry : ClangTidyAliases::activeEntries()) {
+      if (Re.match(Entry.Alias)) {
+        // Alias enabled or disabled: also enable/disable the canonical.
+        OS << ',';
+        if (IsNegative)
+          OS << '-';
+        OS << Entry.Canonical;
+      } else if (IsNegative && Re.match(Entry.Canonical)) {
+        // Canonical disabled: also disable the alias.
+        OS << ",-";
+        OS << Entry.Alias;
+      }
+    }
+  }
+
+  return Result;
+}
+
 void ClangTidyContext::setCurrentFile(StringRef File) {
   CurrentFile = std::string(File);
   CurrentOptions = getOptionsForFile(CurrentFile);
-  CheckFilter = std::make_unique<CachedGlobList>(
-      StringRef(getOptions().Checks.value_or("")));
-  WarningAsErrorFilter = std::make_unique<CachedGlobList>(
-      StringRef(getOptions().WarningsAsErrors.value_or("")));
+  ExpandedChecks = expandCheckAliases(getOptions().Checks.value_or(""));
+  CheckFilter = std::make_unique<CachedGlobList>(StringRef(ExpandedChecks));
+  ExpandedWarningsAsErrors =
+      expandCheckAliases(getOptions().WarningsAsErrors.value_or(""));
+  WarningAsErrorFilter =
+      std::make_unique<CachedGlobList>(StringRef(ExpandedWarningsAsErrors));
   static const std::vector<std::string> EmptyFileExtensions;
   if (!parseFileExtensions(getOptions().HeaderFileExtensions
                                ? *getOptions().HeaderFileExtensions
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index c76f58bc4cc86..168544eabfc0e 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -150,6 +150,9 @@ class ClangTidyContext {
   /// exposed as a 'clang-diagnostic-*' check.
   bool isCompilerDiagnostic(unsigned DiagnosticID) const;
 
+  /// Enable alias usage notifications.
+  void setNotifyAliases(bool Notify) { NotifyAliases = Notify; }
+
   /// Returns \c true if the check is enabled for the \c CurrentFile.
   ///
   /// The \c CurrentFile can be changed using \c setCurrentFile.
@@ -247,9 +250,13 @@ class ClangTidyContext {
   std::string CurrentFile;
   ClangTidyOptions CurrentOptions;
 
+  std::string ExpandedChecks;
+  std::string ExpandedWarningsAsErrors;
   std::unique_ptr<CachedGlobList> CheckFilter;
   std::unique_ptr<CachedGlobList> WarningAsErrorFilter;
 
+  bool NotifyAliases = false;
+
   FileExtensionsSet HeaderFileExtensions;
   FileExtensionsSet ImplementationFileExtensions;
 
diff --git a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h 
b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
index 2450384016e25..590f24fb61a65 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
@@ -18,6 +18,11 @@ extern volatile int AbseilModuleAnchorSource;
 [[maybe_unused]] static int AbseilModuleAnchorDestination =
     AbseilModuleAnchorSource;
 
+// This anchor is used to force the linker to link the AliasesModule.
+extern volatile int AliasesModuleAnchorSource;
+[[maybe_unused]] static int AliasesModuleAnchorDestination =
+    AliasesModuleAnchorSource;
+
 // This anchor is used to force the linker to link the AlteraModule.
 extern volatile int AlteraModuleAnchorSource;
 [[maybe_unused]] static int AlteraModuleAnchorDestination =
diff --git a/clang-tools-extra/clang-tidy/ClangTidyModule.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyModule.cpp
index 976e87dffb0bf..7217dfd1e0652 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyModule.cpp
@@ -12,9 +12,18 @@
 
 #include "ClangTidyModule.h"
 #include "ClangTidyCheck.h"
+#include "aliases/ClangTidyAliases.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
 
 namespace clang::tidy {
 
+/// Returns true if CheckName is an alias whose canonical check is also 
enabled.
+static bool isRedundantAlias(StringRef CheckName, ClangTidyContext *Context) {
+  const StringRef Canonical = 
ClangTidyAliases::getCanonicalForAlias(CheckName);
+  return !Canonical.empty() && Context->isCheckEnabled(Canonical);
+}
+
 void ClangTidyCheckFactories::registerCheckFactory(StringRef Name,
                                                    CheckFactory Factory) {
   Factories.insert_or_assign(Name, std::move(Factory));
@@ -24,7 +33,8 @@ std::vector<std::unique_ptr<ClangTidyCheck>>
 ClangTidyCheckFactories::createChecks(ClangTidyContext *Context) const {
   std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
   for (const auto &[CheckName, Factory] : Factories)
-    if (Context->isCheckEnabled(CheckName))
+    if (Context->isCheckEnabled(CheckName) &&
+        !isRedundantAlias(CheckName, Context))
       Checks.emplace_back(Factory(CheckName, Context));
   return Checks;
 }
@@ -37,6 +47,8 @@ ClangTidyCheckFactories::createChecksForLanguage(
   for (const auto &[CheckName, Factory] : Factories) {
     if (!Context->isCheckEnabled(CheckName))
       continue;
+    if (isRedundantAlias(CheckName, Context))
+      continue;
     std::unique_ptr<ClangTidyCheck> Check = Factory(CheckName, Context);
     if (Check->isLanguageVersionSupported(LO))
       Checks.push_back(std::move(Check));
diff --git a/clang-tools-extra/clang-tidy/ClangTidyModule.h 
b/clang-tools-extra/clang-tidy/ClangTidyModule.h
index 3db92c2dab981..3d84d8f5fd6b1 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyModule.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyModule.h
@@ -10,11 +10,14 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULE_H
 
 #include "ClangTidyOptions.h"
+#include "llvm/ADT/SmallVector.h" // IWYU pragma: keep
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Registry.h"
 #include <functional>
 #include <memory>
+#include <string>
+#include <utility>
 
 namespace clang::tidy {
 
@@ -65,6 +68,23 @@ class ClangTidyCheckFactories {
 
   void eraseCheck(StringRef CheckName) { Factories.erase(CheckName); }
 
+  /// Registers \p AliasName as an alias for check \p CanonicalName.
+  /// The alias is resolved after all modules have registered their checks.
+  void registerCheckAlias(StringRef AliasName, StringRef CanonicalName) {
+    PendingAliases.emplace_back(AliasName, CanonicalName);
+  }
+
+  /// Resolves all pending aliases. Must be called after all modules have
+  /// registered their check factories.
+  void resolveAliases() {
+    for (const auto &[Alias, Canonical] : PendingAliases) {
+      auto It = Factories.find(Canonical);
+      if (It != Factories.end())
+        Factories[Alias] = It->second;
+    }
+    PendingAliases.clear();
+  }
+
   /// Create instances of checks that are enabled.
   std::vector<std::unique_ptr<ClangTidyCheck>>
   createChecks(ClangTidyContext *Context) const;
@@ -80,6 +100,7 @@ class ClangTidyCheckFactories {
 
 private:
   FactoryMap Factories;
+  SmallVector<std::pair<std::string, std::string>> PendingAliases;
 };
 
 /// A clang-tidy module groups a number of \c ClangTidyChecks and gives
diff --git a/clang-tools-extra/clang-tidy/aliases/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/aliases/CMakeLists.txt
new file mode 100644
index 0000000000000..4e39b71827121
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/aliases/CMakeLists.txt
@@ -0,0 +1,21 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  FrontendOpenMP
+  )
+
+add_clang_library(clangTidyAliasesModule STATIC
+  ClangTidyAliases.cpp
+
+  LINK_LIBS
+  clangTidy
+  clangTidyUtils
+
+  DEPENDS
+  omp_gen
+  ClangDriverOptions
+  )
+
+clang_target_link_libraries(clangTidyAliasesModule
+  PRIVATE
+  clangBasic
+  )
diff --git a/clang-tools-extra/clang-tidy/aliases/ClangTidyAliases.cpp 
b/clang-tools-extra/clang-tidy/aliases/ClangTidyAliases.cpp
new file mode 100644
index 0000000000000..e22e3a16e4809
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/aliases/ClangTidyAliases.cpp
@@ -0,0 +1,95 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangTidyAliases.h"
+#include "../ClangTidyModule.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h" // IWYU pragma: keep
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/llvm-config.h"
+#include <cassert>
+
+namespace clang::tidy {
+
+/// Alias table. Kept sorted by alias name for readability.
+static constexpr ClangTidyAliases::Entry AliasTable[] = {
+    // Permanent aliases.
+    {"cert-dcl03-c", "misc-static-assert", ClangTidyAliases::NoExpiration},
+    {"cert-oop11-cpp", "performance-move-constructor-init",
+     ClangTidyAliases::NoExpiration},
+};
+
+ArrayRef<ClangTidyAliases::Entry> ClangTidyAliases::getReference() {
+  return AliasTable;
+}
+
+bool ClangTidyAliases::isActive(const Entry &E) {
+  return E.ExpirationVersion <= NoExpiration ||
+         LLVM_VERSION_MAJOR < E.ExpirationVersion;
+}
+
+ClangTidyAliases::ActiveRange ClangTidyAliases::activeEntries() {
+  return llvm::make_filter_range(getReference(), isActive);
+}
+
+StringRef ClangTidyAliases::getCanonicalForAlias(StringRef Alias) {
+  static const auto *Map = [] {
+    auto *M = new llvm::StringMap<StringRef>();
+    for (const auto &Entry : activeEntries()) {
+      [[maybe_unused]] auto Result =
+          M->try_emplace(Entry.Alias, Entry.Canonical);
+      assert(Result.second && "Duplicate alias in ClangTidyAliases table");
+    }
+    return M;
+  }();
+  auto It = Map->find(Alias);
+  if (It != Map->end())
+    return It->second;
+  return {};
+}
+
+const SmallVector<StringRef> &
+ClangTidyAliases::getAliasesForCanonical(StringRef Canonical) {
+  static const SmallVector<StringRef> Empty;
+  static const auto *ReverseMap = [] {
+    auto *M = new llvm::StringMap<SmallVector<StringRef>>();
+    for (const auto &Entry : activeEntries())
+      (*M)[Entry.Canonical].push_back(Entry.Alias);
+    return M;
+  }();
+  auto It = ReverseMap->find(Canonical);
+  if (It != ReverseMap->end())
+    return It->second;
+  return Empty;
+}
+
+namespace aliases {
+namespace {
+
+class AliasesModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    for (const auto &Entry : ClangTidyAliases::activeEntries())
+      CheckFactories.registerCheckAlias(Entry.Alias, Entry.Canonical);
+  }
+};
+
+} // namespace
+
+static ClangTidyModuleRegistry::Add<AliasesModule>
+    X("aliases-module", "Adds check aliases for backward compatibility.");
+
+} // namespace aliases
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the AliasesModule.
+volatile int AliasesModuleAnchorSource = 0; // 
NOLINT(misc-use-internal-linkage)
+
+} // namespace clang::tidy
diff --git a/clang-tools-extra/clang-tidy/aliases/ClangTidyAliases.h 
b/clang-tools-extra/clang-tidy/aliases/ClangTidyAliases.h
new file mode 100644
index 0000000000000..766291dc191e5
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/aliases/ClangTidyAliases.h
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALIASES_CLANGTIDYALIASES_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALIASES_CLANGTIDYALIASES_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h" // IWYU pragma: keep
+#include "llvm/ADT/StringRef.h"   // IWYU pragma: keep
+
+namespace clang::tidy {
+
+class ClangTidyAliases {
+public:
+  /// Alias never expires.
+  static constexpr int NoExpiration = -1;
+
+  /// An entry in the alias table.
+  /// ExpirationVersion is the LLVM major release at which the alias expires.
+  /// Use NoExpiration for permanent aliases.
+  struct Entry {
+    StringRef Alias;
+    StringRef Canonical;
+    int ExpirationVersion;
+  };
+
+  /// Look up the canonical name for an alias.
+  static StringRef getCanonicalForAlias(StringRef Alias);
+
+  /// Look up aliases for a canonical name (may return multiple).
+  static const SmallVector<StringRef> &
+  getAliasesForCanonical(StringRef Canonical);
+
+  /// Get a reference to the full alias table for iteration.
+  static ArrayRef<Entry> getReference();
+
+  /// Returns true if the given entry is active (not expired) in the current
+  /// LLVM version.
+  static bool isActive(const Entry &E);
+
+  // FIXME: Simplify with std::ranges::views::filter when C++20 is available.
+  using ActiveRange = llvm::iterator_range<
+      llvm::filter_iterator<const Entry *, bool (*)(const Entry &)>>;
+
+  /// Get only active (non-expired) alias entries.
+  static ActiveRange activeEntries();
+};
+
+} // namespace clang::tidy
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALIASES_CLANGTIDYALIASES_H
diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp 
b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
index ee1ce59d80b0d..3a56f5b1f9393 100644
--- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -35,11 +35,9 @@
 #include "../misc/NewDeleteOverloadsCheck.h"
 #include "../misc/NonCopyableObjectsCheck.h"
 #include "../misc/PredictableRandCheck.h"
-#include "../misc/StaticAssertCheck.h"
 #include "../misc/ThrowByValueCatchByReferenceCheck.h"
 #include "../modernize/AvoidSetjmpLongjmpCheck.h"
 #include "../modernize/AvoidVariadicFunctionsCheck.h"
-#include "../performance/MoveConstructorInitCheck.h"
 #include "../readability/EnumInitialValueCheck.h"
 #include "../readability/UppercaseLiteralSuffixCheck.h"
 
@@ -275,8 +273,6 @@ class CERTModule : public ClangTidyModule {
     CheckFactories.registerCheck<bugprone::SignalHandlerCheck>(
         "cert-msc54-cpp");
     // OOP
-    CheckFactories.registerCheck<performance::MoveConstructorInitCheck>(
-        "cert-oop11-cpp");
     CheckFactories.registerCheck<bugprone::UnhandledSelfAssignmentCheck>(
         "cert-oop54-cpp");
     CheckFactories.registerCheck<bugprone::RawMemoryCallOnNonTrivialTypeCheck>(
@@ -292,7 +288,6 @@ class CERTModule : public ClangTidyModule {
     CheckFactories.registerCheck<bugprone::SpuriouslyWakeUpFunctionsCheck>(
         "cert-con36-c");
     // DCL
-    CheckFactories.registerCheck<misc::StaticAssertCheck>("cert-dcl03-c");
     CheckFactories.registerCheck<readability::UppercaseLiteralSuffixCheck>(
         "cert-dcl16-c");
     CheckFactories.registerCheck<bugprone::ReservedIdentifierCheck>(
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp 
b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index 949a88f0fd50d..85b9fea869757 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -18,6 +18,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyForceLinker.h" // IWYU pragma: keep
 #include "../GlobList.h"
+#include "../aliases/ClangTidyAliases.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/CommandLine.h"
@@ -237,6 +238,12 @@ line or a specific configuration file.
 )"),
                                    cl::init(false), 
cl::cat(ClangTidyCategory));
 
+static cl::opt<bool> NotifyAliases("notify-aliases", desc(R"(
+Emit a note for each check alias used in --checks
+or NOLINT comments, showing the canonical check name.
+)"),
+                                   cl::init(false), 
cl::cat(ClangTidyCategory));
+
 static cl::opt<std::string> Config("config", desc(R"(
 Specifies a configuration in YAML/JSON format:
   -config="{Checks: '*',
@@ -658,6 +665,16 @@ int clangTidyMain(int argc, const char **argv) {
       getCheckNames(EffectiveOptions, AllowEnablingAnalyzerAlphaCheckers,
                     ExperimentalCustomChecks);
 
+  if (NotifyAliases) {
+    const GlobList OriginalFilter(
+        StringRef(EffectiveOptions.Checks.value_or("")), false);
+    for (const auto &Entry : ClangTidyAliases::activeEntries())
+      if (OriginalFilter.contains(Entry.Alias))
+        llvm::errs() << "note: '" << Entry.Alias
+                     << "' is an alias for canonical name '" << Entry.Canonical
+                     << "' [checker-alias]\n";
+  }
+
   if (ExplainConfig) {
     // FIXME: Show other ClangTidyOptions' fields, like ExtraArg.
     std::vector<ClangTidyOptionsProvider::OptionsSource> RawOptions =
@@ -737,6 +754,7 @@ int clangTidyMain(int argc, const char **argv) {
   ClangTidyContext Context(
       std::move(OwningOptionsProvider), AllowEnablingAnalyzerAlphaCheckers,
       EnableModuleHeadersParsing, ExperimentalCustomChecks);
+  Context.setNotifyAliases(NotifyAliases);
   std::vector<ClangTidyError> Errors =
       runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS,
                    FixNotes, EnableCheckProfile, ProfilePrefix, Quiet);
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index b1b786cfc4593..baaa76f664401 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -185,6 +185,13 @@ Improvements to clang-query
 Improvements to clang-tidy
 --------------------------
 
+- Added a check alias framework that allows registering alternative names for
+  existing checks. Aliases support bidirectional disable semantics (disabling
+  either the alias or canonical name disables both) and NOLINT suppression
+  using alias names. Added ``--notify-aliases`` option that emits a note for
+  each alias used in ``--checks`` or ``NOLINT`` comments, showing the canonical
+  check name.
+
 - Improved :program:`check_clang_tidy.py` script by adding the `-check-header`
   argument to simplify testing of header files. This argument automatically
   manages the creation of temporary header files and ensures that diagnostics
diff --git a/clang-tools-extra/docs/clang-tidy/index.rst 
b/clang-tools-extra/docs/clang-tidy/index.rst
index 908dee6c18a7f..0d0ead0aad773 100644
--- a/clang-tools-extra/docs/clang-tidy/index.rst
+++ b/clang-tools-extra/docs/clang-tidy/index.rst
@@ -190,6 +190,9 @@ An overview of all the command-line options:
     --explain-config                 - For each enabled check explains, where 
it is
                                        enabled, i.e. in clang-tidy binary, 
command
                                        line or a specific configuration file.
+    --notify-aliases                 - Emit a note for each check alias used in
+                                       --checks or NOLINT comments, showing the
+                                       canonical check name.
     --export-fixes=<filename>        - YAML file to store suggested fixes in. 
The
                                        stored fixes can be applied to the 
input source
                                        code with clang-apply-replacements.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cert/oop11-cpp.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/cert/oop11-cpp.cpp
index f7f3a64867598..e7a8c5706e7b1 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cert/oop11-cpp.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cert/oop11-cpp.cpp
@@ -11,7 +11,7 @@ struct B {
 struct D {
   B b;
 
-  // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: move constructor initializes 
class member by calling a copy constructor [cert-oop11-cpp]
+  // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: move constructor initializes 
class member by calling a copy constructor [performance-move-constructor-init]
   D(D &&d) : b(d.b) {}
 
   // This should not produce a diagnostic because it is not covered under
diff --git a/clang-tools-extra/test/clang-tidy/checkers/check-aliasing.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/check-aliasing.cpp
new file mode 100644
index 0000000000000..e644d35358e73
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/check-aliasing.cpp
@@ -0,0 +1,49 @@
+// Test the clang-tidy check alias framework using permanent cert aliases.
+//
+// Test: enabling alias enables canonical check.
+// RUN: clang-tidy --list-checks --checks='-*,cert-oop11-cpp' 2>&1 | FileCheck 
-check-prefix=ENABLE %s
+//
+// Test: disabling canonical disables alias.
+// RUN: clang-tidy --list-checks --allow-no-checks 
--checks='-*,cert-oop11-cpp,-performance-move-constructor-init' 2>&1 | 
FileCheck -check-prefix=DISABLE %s
+//
+// Test: disabling alias disables canonical.
+// RUN: clang-tidy --list-checks --allow-no-checks 
--checks='-*,performance-move-constructor-init,-cert-oop11-cpp' 2>&1 | 
FileCheck -check-prefix=DISABLE-REVERSE %s
+//
+// Test: --notify-aliases emits note for alias in --checks.
+// RUN: clang-tidy %s --notify-aliases --checks='-*,cert-dcl03-c' -- 
-std=c++11 2>&1 | FileCheck -check-prefix=NOTIFY %s
+//
+// Test: NOLINT with alias name suppresses canonical diagnostic.
+// RUN: clang-tidy %s --checks='-*,cert-oop11-cpp' -- -std=c++11 2>&1 | 
FileCheck -check-prefix=NOLINT-ALIAS %s
+//
+// Test: --warnings-as-errors with alias name promotes canonical diagnostic.
+// RUN: not clang-tidy %s --checks='-*,performance-move-constructor-init' 
--warnings-as-errors='cert-oop11-cpp' -- -std=c++11 2>&1 | FileCheck 
-check-prefix=WARN-AS-ERR %s
+
+// ENABLE-DAG: cert-oop11-cpp
+// ENABLE-DAG: performance-move-constructor-init
+
+// DISABLE-NOT: cert-oop11-cpp
+// DISABLE-NOT: performance-move-constructor-init
+
+// DISABLE-REVERSE-NOT: cert-oop11-cpp
+// DISABLE-REVERSE-NOT: performance-move-constructor-init
+
+// NOTIFY: note: 'cert-dcl03-c' is an alias for canonical name 
'misc-static-assert' [checker-alias]
+
+struct B {
+  B(B &&) noexcept = default;
+  B(const B &) = default;
+  B &operator=(const B &) = default;
+  ~B() {}
+};
+
+struct D {
+  B b;
+  D(D &&d) : b(d.b) {} // NOLINT(cert-oop11-cpp)
+  // NOLINT-ALIAS: Suppressed 1 warnings (1 NOLINT)
+};
+
+struct E {
+  B b;
+  // WARN-AS-ERR: :[[@LINE+1]]:{{.*}} error: {{.*}} 
[performance-move-constructor-init,-warnings-as-errors]
+  E(E &&e) : b(e.b) {}
+};

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to