[clang-tools-extra] Enforce SL.con.3: Add check to replace operator[] with at() [Cont.] (PR #95220)

Paul Heidekrüger via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 5 02:19:07 PST 2024


https://github.com/paulhdk updated https://github.com/llvm/llvm-project/pull/95220

>From c7db969a87aab132a922b23d6f3942571ee4eef4 Mon Sep 17 00:00:00 2001
From: Sebastian Wolf <wolf.sebastian at in.tum.de>
Date: Wed, 17 Apr 2024 16:16:35 +0200
Subject: [PATCH 01/54] Enforce SL.con.3: Add check to replace operator[] with
 at() on std containers

---
 .../AvoidBoundsErrorsCheck.cpp                | 81 +++++++++++++++++++
 .../AvoidBoundsErrorsCheck.h                  | 32 ++++++++
 .../cppcoreguidelines/CMakeLists.txt          |  1 +
 .../CppCoreGuidelinesTidyModule.cpp           |  3 +
 clang-tools-extra/docs/ReleaseNotes.rst       |  5 ++
 .../cppcoreguidelines/avoid-bounds-errors.rst | 20 +++++
 .../docs/clang-tidy/checks/list.rst           |  1 +
 .../cppcoreguidelines/avoid-bounds-errors.cpp | 66 +++++++++++++++
 8 files changed, 209 insertions(+)
 create mode 100644 clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
 create mode 100644 clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
 create mode 100644 clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
new file mode 100644
index 00000000000000..524c21b5bdb818
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
@@ -0,0 +1,81 @@
+//===--- AvoidBoundsErrorsCheck.cpp - clang-tidy --------------------------===//
+//
+// 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 "AvoidBoundsErrorsCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+#include <iostream>
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::cppcoreguidelines {
+
+bool isApplicable(const QualType &Type) {
+  const auto TypeStr = Type.getAsString();
+  bool Result = false;
+  // Only check for containers in the std namespace
+  if (TypeStr.find("std::vector") != std::string::npos) {
+    Result = true;
+  }
+  if (TypeStr.find("std::array") != std::string::npos) {
+    Result = true;
+  }
+  if (TypeStr.find("std::deque") != std::string::npos) {
+    Result = true;
+  }
+  if (TypeStr.find("std::map") != std::string::npos) {
+    Result = true;
+  }
+  if (TypeStr.find("std::unordered_map") != std::string::npos) {
+    Result = true;
+  }
+  if (TypeStr.find("std::flat_map") != std::string::npos) {
+    Result = true;
+  }
+  // TODO Add std::span with C++26
+  return Result;
+}
+
+void AvoidBoundsErrorsCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      callExpr(callee(cxxMethodDecl(hasName("operator[]")).bind("f")))
+          .bind("x"),
+      this);
+}
+
+void AvoidBoundsErrorsCheck::check(const MatchFinder::MatchResult &Result) {
+  const ASTContext &Context = *Result.Context;
+  const SourceManager &Source = Context.getSourceManager();
+  const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("x");
+  const auto *MatchedFunction = Result.Nodes.getNodeAs<CXXMethodDecl>("f");
+  const auto Type = MatchedFunction->getThisType();
+  if (!isApplicable(Type)) {
+    return;
+  }
+
+  // Get original code.
+  const SourceLocation b(MatchedExpr->getBeginLoc());
+  const SourceLocation e(MatchedExpr->getEndLoc());
+  const std::string OriginalCode =
+      Lexer::getSourceText(CharSourceRange::getTokenRange(b, e), Source,
+                           getLangOpts())
+          .str();
+  const auto Range = SourceRange(b, e);
+
+  // Build replacement.
+  std::string NewCode = OriginalCode;
+  const auto BeginOpen = NewCode.find("[");
+  NewCode.replace(BeginOpen, 1, ".at(");
+  const auto BeginClose = NewCode.find("]");
+  NewCode.replace(BeginClose, 1, ")");
+
+  diag(MatchedExpr->getBeginLoc(), "Do not use operator[], use at() instead.")
+      << FixItHint::CreateReplacement(Range, NewCode);
+}
+
+} // namespace clang::tidy::cppcoreguidelines
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
new file mode 100644
index 00000000000000..f915729cd7bbee
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
@@ -0,0 +1,32 @@
+//===--- AvoidBoundsErrorsCheck.h - clang-tidy ------------------*- C++ -*-===//
+//
+// 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_CPPCOREGUIDELINES_AVOIDBOUNDSERRORSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDBOUNDSERRORSCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::cppcoreguidelines {
+
+/// Enforce CPP core guidelines SL.con.3
+///
+/// See
+/// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.html
+class AvoidBoundsErrorsCheck : public ClangTidyCheck {
+public:
+  AvoidBoundsErrorsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace clang::tidy::cppcoreguidelines
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDBOUNDSERRORSCHECK_H
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
index 07bb89ec7937a0..52647a1b946f6f 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_clang_library(clangTidyCppCoreGuidelinesModule STATIC
+  AvoidBoundsErrorsCheck.cpp
   AvoidCapturingLambdaCoroutinesCheck.cpp
   AvoidConstOrRefDataMembersCheck.cpp
   AvoidDoWhileCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
index e9f0201615616f..525bbc7a42adaa 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -19,6 +19,7 @@
 #include "../performance/NoexceptMoveConstructorCheck.h"
 #include "../performance/NoexceptSwapCheck.h"
 #include "../readability/MagicNumbersCheck.h"
+#include "AvoidBoundsErrorsCheck.h"
 #include "AvoidCapturingLambdaCoroutinesCheck.h"
 #include "AvoidConstOrRefDataMembersCheck.h"
 #include "AvoidDoWhileCheck.h"
@@ -57,6 +58,8 @@ namespace cppcoreguidelines {
 class CppCoreGuidelinesModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<AvoidBoundsErrorsCheck>(
+        "cppcoreguidelines-avoid-bounds-errors");
     CheckFactories.registerCheck<AvoidCapturingLambdaCoroutinesCheck>(
         "cppcoreguidelines-avoid-capturing-lambda-coroutines");
     CheckFactories.registerCheck<modernize::AvoidCArraysCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 51ba157ab05deb..b7b812952dd2f7 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -137,6 +137,11 @@ New checks
   Finds cases when an uninstantiated virtual member function in a template class 
   causes cross-compiler incompatibility.
 
+- New :doc:`cppcoreguidelines-avoid-bounds-errors
+  <clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors>` check.
+
+  Flags the unsafe `operator[]` and replaces it with `at()`.
+
 New check aliases
 ^^^^^^^^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
new file mode 100644
index 00000000000000..8fb2e3bfde0981
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - cppcoreguidelines-avoid-bounds-errors
+
+cppcoreguidelines-avoid-bounds-errors
+=====================================
+
+This check enforces the `SL.con.3 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>` guideline.
+It flags all uses of `operator[]` on `std::vector`, `std::array`, `std::deque`, `std::map`, `std::unordered_map`, and `std::flat_map` and suggests to replace it with `at()`.
+Note that `std::span` and `std::mdspan` do not support `at()` as of C++23, so the use of `operator[]` is not flagged.
+
+For example the code
+
+.. code-block:: c++
+  std::array<int, 3> a;
+  int b = a[4];
+
+will be replaced by 
+
+.. code-block:: c++
+  std::vector<int, 3> a;
+  int b = a.at(4);
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index d731b13fc0df44..d9d55b5f55fb0b 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -179,6 +179,7 @@ Clang-Tidy Checks
    :doc:`cert-oop58-cpp <cert/oop58-cpp>`,
    :doc:`concurrency-mt-unsafe <concurrency/mt-unsafe>`,
    :doc:`concurrency-thread-canceltype-asynchronous <concurrency/thread-canceltype-asynchronous>`,
+   :doc:`cppcoreguidelines-avoid-bounds-errors <cppcoreguidelines/avoid-bounds-errors>`, "Yes"
    :doc:`cppcoreguidelines-avoid-capturing-lambda-coroutines <cppcoreguidelines/avoid-capturing-lambda-coroutines>`,
    :doc:`cppcoreguidelines-avoid-const-or-ref-data-members <cppcoreguidelines/avoid-const-or-ref-data-members>`,
    :doc:`cppcoreguidelines-avoid-do-while <cppcoreguidelines/avoid-do-while>`,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp
new file mode 100644
index 00000000000000..23453b1f2df218
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp
@@ -0,0 +1,66 @@
+namespace std {
+  template<typename T, unsigned size>
+  struct array {
+    T operator[](unsigned i) {
+      return T{1};
+    }
+    T at(unsigned i) {
+      return T{1};
+    }
+  };
+
+  template<typename T>
+  struct unique_ptr {
+    T operator[](unsigned i) {
+      return T{1};
+    }
+  };
+
+  template<typename T>
+  struct span {
+    T operator[](unsigned i) {
+      return T{1};
+    }
+  };
+} // namespace std
+
+namespace json {
+  template<typename T>
+  struct node{
+    T operator[](unsigned i) {
+      return T{1};
+    }
+  };
+} // namespace json
+
+
+// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-bounds-errors %t
+std::array<int, 3> a;
+
+auto b = a[0];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Do not use operator[], use at() instead. [cppcoreguidelines-avoid-bounds-errors]
+// CHECK-FIXES: auto b = a.at(0);
+auto c = a[1+1];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Do not use operator[], use at() instead. [cppcoreguidelines-avoid-bounds-errors]
+// CHECK-FIXES: auto c = a.at(1+1);
+constexpr int index = 1;
+auto d = a[index];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Do not use operator[], use at() instead. [cppcoreguidelines-avoid-bounds-errors]
+// CHECK-FIXES: auto d = a.at(index);
+
+int e(int index) {
+  return a[index];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Do not use operator[], use at() instead. [cppcoreguidelines-avoid-bounds-errors]
+// CHECK-FIXES: return a.at(index);
+}
+
+auto f = a.at(0);
+
+std::unique_ptr<int> p;
+auto q = p[0];
+
+std::span<int> s;
+auto t = s[0];
+
+json::node<int> n;
+auto m = n[0];

>From c8d415278bba3afc547ea2fc91907ceb9dece6ee Mon Sep 17 00:00:00 2001
From: Sebastian Wolf <wolf.sebastian at in.tum.de>
Date: Fri, 26 Apr 2024 09:06:02 +0200
Subject: [PATCH 02/54] EugeneZelenko's comments

---
 .../cppcoreguidelines/AvoidBoundsErrorsCheck.cpp       | 10 +++++-----
 .../cppcoreguidelines/AvoidBoundsErrorsCheck.h         |  3 +++
 clang-tools-extra/docs/ReleaseNotes.rst                |  2 +-
 .../checks/cppcoreguidelines/avoid-bounds-errors.rst   |  7 ++++---
 4 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
index 524c21b5bdb818..2c0a12e21d726b 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
@@ -9,13 +9,13 @@
 #include "AvoidBoundsErrorsCheck.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Lex/Lexer.h"
-
 #include <iostream>
+
 using namespace clang::ast_matchers;
 
 namespace clang::tidy::cppcoreguidelines {
 
-bool isApplicable(const QualType &Type) {
+static bool isApplicable(const QualType &Type) {
   const auto TypeStr = Type.getAsString();
   bool Result = false;
   // Only check for containers in the std namespace
@@ -51,9 +51,9 @@ void AvoidBoundsErrorsCheck::registerMatchers(MatchFinder *Finder) {
 void AvoidBoundsErrorsCheck::check(const MatchFinder::MatchResult &Result) {
   const ASTContext &Context = *Result.Context;
   const SourceManager &Source = Context.getSourceManager();
-  const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("x");
-  const auto *MatchedFunction = Result.Nodes.getNodeAs<CXXMethodDecl>("f");
-  const auto Type = MatchedFunction->getThisType();
+  const CallExpr *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("x");
+  const CXXMethodDecl *MatchedFunction = Result.Nodes.getNodeAs<CXXMethodDecl>("f");
+  const QualType Type = MatchedFunction->getThisType();
   if (!isApplicable(Type)) {
     return;
   }
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
index f915729cd7bbee..12c78528771234 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
@@ -23,6 +23,9 @@ class AvoidBoundsErrorsCheck : public ClangTidyCheck {
 public:
   AvoidBoundsErrorsCheck(StringRef Name, ClangTidyContext *Context)
       : ClangTidyCheck(Name, Context) {}
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus;
+  }
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
 };
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b7b812952dd2f7..95c1d8587fec4e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -140,7 +140,7 @@ New checks
 - New :doc:`cppcoreguidelines-avoid-bounds-errors
   <clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors>` check.
 
-  Flags the unsafe `operator[]` and replaces it with `at()`.
+  Flags the unsafe ``operator[]`` and replaces it with ``at()``.
 
 New check aliases
 ^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
index 8fb2e3bfde0981..13683ee9b5a467 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
@@ -3,9 +3,8 @@
 cppcoreguidelines-avoid-bounds-errors
 =====================================
 
-This check enforces the `SL.con.3 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>` guideline.
-It flags all uses of `operator[]` on `std::vector`, `std::array`, `std::deque`, `std::map`, `std::unordered_map`, and `std::flat_map` and suggests to replace it with `at()`.
-Note that `std::span` and `std::mdspan` do not support `at()` as of C++23, so the use of `operator[]` is not flagged.
+This check flags all uses of ``operator[]`` on ``std::vector``, ``std::array``, ``std::deque``, ``std::map``, ``std::unordered_map``, and ``std::flat_map`` and suggests to replace it with ``at()``.
+Note that ``std::span`` and ``std::mdspan`` do not support ``at()`` as of C++23, so the use of ``operator[]`` is not flagged.
 
 For example the code
 
@@ -18,3 +17,5 @@ will be replaced by
 .. code-block:: c++
   std::vector<int, 3> a;
   int b = a.at(4);
+
+This check enforces the `SL.con.3 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>` guideline.

>From fd0977554e55b20e36361371c522b8677cfa83a3 Mon Sep 17 00:00:00 2001
From: Sebastian Wolf <wolf.sebastian at in.tum.de>
Date: Fri, 24 May 2024 12:09:11 +0200
Subject: [PATCH 03/54] Refactoring, but not finished yet

---
 .../AvoidBoundsErrorsCheck.cpp                | 97 ++++++++++---------
 .../cppcoreguidelines/avoid-bounds-errors.cpp | 17 ++--
 2 files changed, 57 insertions(+), 57 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
index 2c0a12e21d726b..f10b97820f4c7d 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
@@ -9,73 +9,74 @@
 #include "AvoidBoundsErrorsCheck.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Lex/Lexer.h"
-#include <iostream>
 
 using namespace clang::ast_matchers;
 
 namespace clang::tidy::cppcoreguidelines {
 
-static bool isApplicable(const QualType &Type) {
-  const auto TypeStr = Type.getAsString();
-  bool Result = false;
-  // Only check for containers in the std namespace
-  if (TypeStr.find("std::vector") != std::string::npos) {
-    Result = true;
-  }
-  if (TypeStr.find("std::array") != std::string::npos) {
-    Result = true;
-  }
-  if (TypeStr.find("std::deque") != std::string::npos) {
-    Result = true;
-  }
-  if (TypeStr.find("std::map") != std::string::npos) {
-    Result = true;
-  }
-  if (TypeStr.find("std::unordered_map") != std::string::npos) {
-    Result = true;
-  }
-  if (TypeStr.find("std::flat_map") != std::string::npos) {
-    Result = true;
+const CXXMethodDecl *findAlternative(const CXXRecordDecl *MatchedParent,
+                                     const CXXMethodDecl *MatchedOperator) {
+  for (const CXXMethodDecl *Method : MatchedParent->methods()) {
+    const bool CorrectName = Method->getNameInfo().getAsString() == "at";
+    if (!CorrectName)
+      continue;
+
+    const bool SameReturnType =
+        Method->getReturnType() == MatchedOperator->getReturnType();
+    if (!SameReturnType)
+      continue;
+
+    const bool SameNumberOfArguments =
+        Method->getNumParams() == MatchedOperator->getNumParams();
+    if (!SameNumberOfArguments)
+      continue;
+
+    for (unsigned a = 0; a < Method->getNumParams(); a++) {
+      const bool SameArgType =
+          Method->parameters()[a]->getOriginalType() ==
+          MatchedOperator->parameters()[a]->getOriginalType();
+      if (!SameArgType)
+        continue;
+    }
+
+    return Method;
   }
-  // TODO Add std::span with C++26
-  return Result;
+  return static_cast<CXXMethodDecl *>(nullptr);
 }
 
 void AvoidBoundsErrorsCheck::registerMatchers(MatchFinder *Finder) {
+  // Need a callExpr here to match CXXOperatorCallExpr ``(&a)->operator[](0)``
+  // and CXXMemberCallExpr ``a[0]``.
   Finder->addMatcher(
-      callExpr(callee(cxxMethodDecl(hasName("operator[]")).bind("f")))
-          .bind("x"),
+      callExpr(
+          callee(
+              cxxMethodDecl(hasOverloadedOperatorName("[]")).bind("operator")),
+          callee(cxxMethodDecl(hasParent(
+              cxxRecordDecl(hasMethod(hasName("at"))).bind("parent")))))
+          .bind("caller"),
       this);
 }
 
 void AvoidBoundsErrorsCheck::check(const MatchFinder::MatchResult &Result) {
   const ASTContext &Context = *Result.Context;
   const SourceManager &Source = Context.getSourceManager();
-  const CallExpr *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("x");
-  const CXXMethodDecl *MatchedFunction = Result.Nodes.getNodeAs<CXXMethodDecl>("f");
-  const QualType Type = MatchedFunction->getThisType();
-  if (!isApplicable(Type)) {
-    return;
-  }
+  const CallExpr *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
+  const CXXMethodDecl *MatchedOperator =
+      Result.Nodes.getNodeAs<CXXMethodDecl>("operator");
+  const CXXRecordDecl *MatchedParent =
+      Result.Nodes.getNodeAs<CXXRecordDecl>("parent");
 
-  // Get original code.
-  const SourceLocation b(MatchedExpr->getBeginLoc());
-  const SourceLocation e(MatchedExpr->getEndLoc());
-  const std::string OriginalCode =
-      Lexer::getSourceText(CharSourceRange::getTokenRange(b, e), Source,
-                           getLangOpts())
-          .str();
-  const auto Range = SourceRange(b, e);
+  const CXXMethodDecl *Alternative =
+      findAlternative(MatchedParent, MatchedOperator);
+  if (!Alternative)
+    return;
 
-  // Build replacement.
-  std::string NewCode = OriginalCode;
-  const auto BeginOpen = NewCode.find("[");
-  NewCode.replace(BeginOpen, 1, ".at(");
-  const auto BeginClose = NewCode.find("]");
-  NewCode.replace(BeginClose, 1, ")");
+  const SourceLocation AlternativeSource(Alternative->getBeginLoc());
 
-  diag(MatchedExpr->getBeginLoc(), "Do not use operator[], use at() instead.")
-      << FixItHint::CreateReplacement(Range, NewCode);
+  diag(MatchedExpr->getBeginLoc(),
+       "found possibly unsafe operator[], consider using at() instead");
+  diag(Alternative->getBeginLoc(), "alternative at() defined here",
+       DiagnosticIDs::Note);
 }
 
 } // namespace clang::tidy::cppcoreguidelines
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp
index 23453b1f2df218..5e12e7d71790d0 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp
@@ -38,23 +38,22 @@ namespace json {
 std::array<int, 3> a;
 
 auto b = a[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Do not use operator[], use at() instead. [cppcoreguidelines-avoid-bounds-errors]
-// CHECK-FIXES: auto b = a.at(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
 auto c = a[1+1];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Do not use operator[], use at() instead. [cppcoreguidelines-avoid-bounds-errors]
-// CHECK-FIXES: auto c = a.at(1+1);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
 constexpr int index = 1;
 auto d = a[index];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Do not use operator[], use at() instead. [cppcoreguidelines-avoid-bounds-errors]
-// CHECK-FIXES: auto d = a.at(index);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
 
 int e(int index) {
   return a[index];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Do not use operator[], use at() instead. [cppcoreguidelines-avoid-bounds-errors]
-// CHECK-FIXES: return a.at(index);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
 }
 
-auto f = a.at(0);
+auto f = (&a)->operator[](1);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
+
+auto g = a.at(0);
 
 std::unique_ptr<int> p;
 auto q = p[0];

>From 12b548dbb0db9436f95afea54e0cc14c1887190a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 10 Jun 2024 20:56:39 +0200
Subject: [PATCH 04/54] Rename AvoidBoundsErrorsCheck to
 PreferAtOverSubscriptOperatorCheck

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../cppcoreguidelines/CMakeLists.txt          |  2 +-
 .../CppCoreGuidelinesTidyModule.cpp           |  6 +--
 ...=> PreferAtOverSubscriptOperatorCheck.cpp} |  9 +++--
 ...h => PreferAtOverSubscriptOperatorCheck.h} | 16 ++++----
 clang-tools-extra/docs/ReleaseNotes.rst       | 38 +++++++++++++++++--
 ... => prefer-at-over-subscript-operator.rst} |  4 +-
 .../docs/clang-tidy/checks/list.rst           |  2 +-
 ... => prefer-at-over-subscript-operator.cpp} | 12 +++---
 8 files changed, 61 insertions(+), 28 deletions(-)
 rename clang-tools-extra/clang-tidy/cppcoreguidelines/{AvoidBoundsErrorsCheck.cpp => PreferAtOverSubscriptOperatorCheck.cpp} (90%)
 rename clang-tools-extra/clang-tidy/cppcoreguidelines/{AvoidBoundsErrorsCheck.h => PreferAtOverSubscriptOperatorCheck.h} (60%)
 rename clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/{avoid-bounds-errors.rst => prefer-at-over-subscript-operator.rst} (83%)
 rename clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/{avoid-bounds-errors.cpp => prefer-at-over-subscript-operator.cpp} (67%)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
index 52647a1b946f6f..a9444d33e2f304 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -4,7 +4,6 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_clang_library(clangTidyCppCoreGuidelinesModule STATIC
-  AvoidBoundsErrorsCheck.cpp
   AvoidCapturingLambdaCoroutinesCheck.cpp
   AvoidConstOrRefDataMembersCheck.cpp
   AvoidDoWhileCheck.cpp
@@ -21,6 +20,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule STATIC
   NoMallocCheck.cpp
   NoSuspendWithLockCheck.cpp
   OwningMemoryCheck.cpp
+  PreferAtOverSubscriptOperatorCheck.cpp
   PreferMemberInitializerCheck.cpp
   ProBoundsArrayToPointerDecayCheck.cpp
   ProBoundsConstantArrayIndexCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
index 525bbc7a42adaa..565a99a865519c 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -19,7 +19,6 @@
 #include "../performance/NoexceptMoveConstructorCheck.h"
 #include "../performance/NoexceptSwapCheck.h"
 #include "../readability/MagicNumbersCheck.h"
-#include "AvoidBoundsErrorsCheck.h"
 #include "AvoidCapturingLambdaCoroutinesCheck.h"
 #include "AvoidConstOrRefDataMembersCheck.h"
 #include "AvoidDoWhileCheck.h"
@@ -35,6 +34,7 @@
 #include "NoMallocCheck.h"
 #include "NoSuspendWithLockCheck.h"
 #include "OwningMemoryCheck.h"
+#include "PreferAtOverSubscriptOperatorCheck.h"
 #include "PreferMemberInitializerCheck.h"
 #include "ProBoundsArrayToPointerDecayCheck.h"
 #include "ProBoundsConstantArrayIndexCheck.h"
@@ -58,8 +58,6 @@ namespace cppcoreguidelines {
 class CppCoreGuidelinesModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
-    CheckFactories.registerCheck<AvoidBoundsErrorsCheck>(
-        "cppcoreguidelines-avoid-bounds-errors");
     CheckFactories.registerCheck<AvoidCapturingLambdaCoroutinesCheck>(
         "cppcoreguidelines-avoid-capturing-lambda-coroutines");
     CheckFactories.registerCheck<modernize::AvoidCArraysCheck>(
@@ -105,6 +103,8 @@ class CppCoreGuidelinesModule : public ClangTidyModule {
         "cppcoreguidelines-non-private-member-variables-in-classes");
     CheckFactories.registerCheck<OwningMemoryCheck>(
         "cppcoreguidelines-owning-memory");
+    CheckFactories.registerCheck<PreferAtOverSubscriptOperatorCheck>(
+        "cppcoreguidelines-prefer-at-over-subscript-operator");
     CheckFactories.registerCheck<PreferMemberInitializerCheck>(
         "cppcoreguidelines-prefer-member-initializer");
     CheckFactories.registerCheck<ProBoundsArrayToPointerDecayCheck>(
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
similarity index 90%
rename from clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
rename to clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
index f10b97820f4c7d..64eaf8a1d4ebd5 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
@@ -1,4 +1,4 @@
-//===--- AvoidBoundsErrorsCheck.cpp - clang-tidy --------------------------===//
+//===--- PreferAtOverSubscriptOperatorCheck.cpp - clang-tidy --------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "AvoidBoundsErrorsCheck.h"
+#include "PreferAtOverSubscriptOperatorCheck.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Lex/Lexer.h"
 
@@ -44,7 +44,7 @@ const CXXMethodDecl *findAlternative(const CXXRecordDecl *MatchedParent,
   return static_cast<CXXMethodDecl *>(nullptr);
 }
 
-void AvoidBoundsErrorsCheck::registerMatchers(MatchFinder *Finder) {
+void PreferAtOverSubscriptOperatorCheck::registerMatchers(MatchFinder *Finder) {
   // Need a callExpr here to match CXXOperatorCallExpr ``(&a)->operator[](0)``
   // and CXXMemberCallExpr ``a[0]``.
   Finder->addMatcher(
@@ -57,7 +57,8 @@ void AvoidBoundsErrorsCheck::registerMatchers(MatchFinder *Finder) {
       this);
 }
 
-void AvoidBoundsErrorsCheck::check(const MatchFinder::MatchResult &Result) {
+void PreferAtOverSubscriptOperatorCheck::check(
+    const MatchFinder::MatchResult &Result) {
   const ASTContext &Context = *Result.Context;
   const SourceManager &Source = Context.getSourceManager();
   const CallExpr *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h
similarity index 60%
rename from clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
rename to clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h
index 12c78528771234..eb6e3a021e1b6c 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h
@@ -1,4 +1,5 @@
-//===--- AvoidBoundsErrorsCheck.h - clang-tidy ------------------*- C++ -*-===//
+//===--- PreferAtOverSubscriptOperatorCheck.h - clang-tidy ------*- C++ -*-===//
+//===--- PreferMemberInitializerCheck.h - clang-tidy ------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDBOUNDSERRORSCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDBOUNDSERRORSCHECK_H
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERATOVERSUBSCRIPTOPERATORCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERATOVERSUBSCRIPTOPERATORCHECK_H
 
 #include "../ClangTidyCheck.h"
 
@@ -18,11 +19,10 @@ namespace clang::tidy::cppcoreguidelines {
 /// See
 /// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors
 /// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.html
-class AvoidBoundsErrorsCheck : public ClangTidyCheck {
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.html
+class PreferAtOverSubscriptOperatorCheck : public ClangTidyCheck {
 public:
-  AvoidBoundsErrorsCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+  PreferAtOverSubscriptOperatorCheck(StringRef Name, ClangTidyContext *Context);
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
     return LangOpts.CPlusPlus;
   }
@@ -32,4 +32,4 @@ class AvoidBoundsErrorsCheck : public ClangTidyCheck {
 
 } // namespace clang::tidy::cppcoreguidelines
 
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDBOUNDSERRORSCHECK_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERATOVERSUBSCRIPTOPERATORCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 95c1d8587fec4e..7f65d5f34108c3 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -137,10 +137,42 @@ New checks
   Finds cases when an uninstantiated virtual member function in a template class 
   causes cross-compiler incompatibility.
 
-- New :doc:`cppcoreguidelines-avoid-bounds-errors
-  <clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors>` check.
+- New :doc:`bugprone-crtp-constructor-accessibility
+  <clang-tidy/checks/bugprone/crtp-constructor-accessibility>` check.
 
-  Flags the unsafe ``operator[]`` and replaces it with ``at()``.
+  Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP
+  can be constructed outside itself and the derived class.
+
+- New :doc:`bugprone-return-const-ref-from-parameter
+  <clang-tidy/checks/bugprone/return-const-ref-from-parameter>` check.
+
+  Detects return statements that return a constant reference parameter as constant
+  reference. This may cause use-after-free errors if the caller uses xvalues as
+  arguments.
+
+- New :doc:`bugprone-suspicious-stringview-data-usage
+  <clang-tidy/checks/bugprone/suspicious-stringview-data-usage>` check.
+
+  Identifies suspicious usages of ``std::string_view::data()`` that could lead
+  to reading out-of-bounds data due to inadequate or incorrect string null
+  termination.
+
+- New :doc:`misc-use-internal-linkage
+  <clang-tidy/checks/misc/use-internal-linkage>` check.
+
+  Detects variables and functions that can be marked as static or moved into
+  an anonymous namespace to enforce internal linkage.
+
+- New :doc:`modernize-min-max-use-initializer-list
+  <clang-tidy/checks/modernize/min-max-use-initializer-list>` check.
+
+  Replaces nested ``std::min`` and ``std::max`` calls with an initializer list
+  where applicable.
+
+- New :doc:`cppcoreguidelines-prefer-at-over-subscript-operator
+  <clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator>` check.
+
+  Flags the unsafe ``operator[]`` and suggests replacing it with ``at()``.
 
 New check aliases
 ^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
similarity index 83%
rename from clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
rename to clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
index 13683ee9b5a467..183175b5966682 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
@@ -1,6 +1,6 @@
-.. title:: clang-tidy - cppcoreguidelines-avoid-bounds-errors
+.. title:: clang-tidy - cppcoreguidelines-prefer-at-over-subscript-operator
 
-cppcoreguidelines-avoid-bounds-errors
+cppcoreguidelines-prefer-at-over-subscript-operator
 =====================================
 
 This check flags all uses of ``operator[]`` on ``std::vector``, ``std::array``, ``std::deque``, ``std::map``, ``std::unordered_map``, and ``std::flat_map`` and suggests to replace it with ``at()``.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index d9d55b5f55fb0b..3b1010b495608b 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -179,7 +179,6 @@ Clang-Tidy Checks
    :doc:`cert-oop58-cpp <cert/oop58-cpp>`,
    :doc:`concurrency-mt-unsafe <concurrency/mt-unsafe>`,
    :doc:`concurrency-thread-canceltype-asynchronous <concurrency/thread-canceltype-asynchronous>`,
-   :doc:`cppcoreguidelines-avoid-bounds-errors <cppcoreguidelines/avoid-bounds-errors>`, "Yes"
    :doc:`cppcoreguidelines-avoid-capturing-lambda-coroutines <cppcoreguidelines/avoid-capturing-lambda-coroutines>`,
    :doc:`cppcoreguidelines-avoid-const-or-ref-data-members <cppcoreguidelines/avoid-const-or-ref-data-members>`,
    :doc:`cppcoreguidelines-avoid-do-while <cppcoreguidelines/avoid-do-while>`,
@@ -195,6 +194,7 @@ Clang-Tidy Checks
    :doc:`cppcoreguidelines-no-malloc <cppcoreguidelines/no-malloc>`,
    :doc:`cppcoreguidelines-no-suspend-with-lock <cppcoreguidelines/no-suspend-with-lock>`,
    :doc:`cppcoreguidelines-owning-memory <cppcoreguidelines/owning-memory>`,
+   :doc:`cppcoreguidelines-prefer-at-over-subscript-operator <cppcoreguidelines/prefer-at-over-subscript-operator>`,
    :doc:`cppcoreguidelines-prefer-member-initializer <cppcoreguidelines/prefer-member-initializer>`, "Yes"
    :doc:`cppcoreguidelines-pro-bounds-array-to-pointer-decay <cppcoreguidelines/pro-bounds-array-to-pointer-decay>`,
    :doc:`cppcoreguidelines-pro-bounds-constant-array-index <cppcoreguidelines/pro-bounds-constant-array-index>`, "Yes"
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
similarity index 67%
rename from clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp
rename to clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
index 5e12e7d71790d0..45071f8f9f2078 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
@@ -34,24 +34,24 @@ namespace json {
 } // namespace json
 
 
-// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-bounds-errors %t
+// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-at-over-subscript-operator %t
 std::array<int, 3> a;
 
 auto b = a[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
 auto c = a[1+1];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
 constexpr int index = 1;
 auto d = a[index];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
 
 int e(int index) {
   return a[index];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
 }
 
 auto f = (&a)->operator[](1);
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-avoid-bounds-errors]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
 
 auto g = a.at(0);
 

>From 6a7ab8bf3abcf1b6018c2283a3322df6be7a6880 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 10 Jun 2024 22:14:54 +0200
Subject: [PATCH 05/54] Add a user-customizable mechanism for excluding classes
 from the analysis

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../PreferAtOverSubscriptOperatorCheck.cpp    | 49 +++++++++++++++++--
 .../PreferAtOverSubscriptOperatorCheck.h      |  5 ++
 .../prefer-at-over-subscript-operator.cpp     | 36 +++++++++++++-
 3 files changed, 86 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
index 64eaf8a1d4ebd5..d7cdbc59d39410 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
@@ -7,13 +7,52 @@
 //===----------------------------------------------------------------------===//
 
 #include "PreferAtOverSubscriptOperatorCheck.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringRef.h"
+#include <algorithm>
+#include <numeric>
 
 using namespace clang::ast_matchers;
 
 namespace clang::tidy::cppcoreguidelines {
 
+static constexpr std::array<llvm::StringRef, 3> DefaultExclusions = {
+    llvm::StringRef("std::map"), llvm::StringRef("std::unordered_map"),
+    llvm::StringRef("std::flat_map")};
+
+PreferAtOverSubscriptOperatorCheck::PreferAtOverSubscriptOperatorCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context) {
+
+  ExcludedClasses = clang::tidy::utils::options::parseStringList(
+      Options.get("ExcludeClasses", ""));
+  ExcludedClasses.insert(ExcludedClasses.end(), DefaultExclusions.begin(),
+                         DefaultExclusions.end());
+}
+
+void PreferAtOverSubscriptOperatorCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+
+  if (ExcludedClasses.size() == DefaultExclusions.size()) {
+    Options.store(Opts, "ExcludeClasses", "");
+    return;
+  }
+
+  // Sum up the sizes of the defaults ( + semicolons), so we can remove them
+  // from the saved options
+  size_t DefaultsStringLength =
+      std::transform_reduce(DefaultExclusions.begin(), DefaultExclusions.end(),
+                            DefaultExclusions.size(), std::plus<>(),
+                            [](llvm::StringRef Name) { return Name.size(); });
+
+  std::string Serialized =
+      clang::tidy::utils::options::serializeStringList(ExcludedClasses);
+
+  Options.store(Opts, "ExcludeClasses",
+                Serialized.substr(0, Serialized.size() - DefaultsStringLength));
+}
+
 const CXXMethodDecl *findAlternative(const CXXRecordDecl *MatchedParent,
                                      const CXXMethodDecl *MatchedOperator) {
   for (const CXXMethodDecl *Method : MatchedParent->methods()) {
@@ -67,13 +106,17 @@ void PreferAtOverSubscriptOperatorCheck::check(
   const CXXRecordDecl *MatchedParent =
       Result.Nodes.getNodeAs<CXXRecordDecl>("parent");
 
+  std::string ClassIdentifier = MatchedParent->getQualifiedNameAsString();
+
+  if (std::find(ExcludedClasses.begin(), ExcludedClasses.end(),
+                ClassIdentifier) != ExcludedClasses.end())
+    return;
+
   const CXXMethodDecl *Alternative =
       findAlternative(MatchedParent, MatchedOperator);
   if (!Alternative)
     return;
 
-  const SourceLocation AlternativeSource(Alternative->getBeginLoc());
-
   diag(MatchedExpr->getBeginLoc(),
        "found possibly unsafe operator[], consider using at() instead");
   diag(Alternative->getBeginLoc(), "alternative at() defined here",
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h
index eb6e3a021e1b6c..f2450a7ab34708 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h
@@ -28,6 +28,11 @@ class PreferAtOverSubscriptOperatorCheck : public ClangTidyCheck {
   }
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  // A list of class names that are excluded from the warning
+  std::vector<llvm::StringRef> ExcludedClasses;
 };
 
 } // namespace clang::tidy::cppcoreguidelines
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
index 45071f8f9f2078..7da6c315569699 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
@@ -34,7 +34,30 @@ namespace json {
 } // namespace json
 
 
-// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-at-over-subscript-operator %t
+class ExcludedClass1 {
+  public:
+    int operator[](unsigned i) {
+      return 1;
+    }
+    int at(unsigned i) {
+      return 1;
+    }
+};
+
+class ExcludedClass2 {
+  public:
+    int operator[](unsigned i) {
+      return 1;
+    }
+    int at(unsigned i) {
+      return 1;
+    }
+};
+
+
+// RUN: %check_clang_tidy %s \
+// RUN: cppcoreguidelines-prefer-at-over-subscript-operator %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-prefer-at-over-subscript-operator.ExcludeClasses: "ExcludedClass1;ExcludedClass2"}}'
 std::array<int, 3> a;
 
 auto b = a[0];
@@ -63,3 +86,14 @@ auto t = s[0];
 
 json::node<int> n;
 auto m = n[0];
+
+//explicitely excluded classes / struct / template
+ExcludedClass1 E1;
+auto x1 = E1[0];
+
+ExcludedClass2 E2;
+auto x2 = E1[0];
+
+std::map<int,int> TestMap;
+auto y = TestMap[0];
+

>From 6ede5097e56527a502f05d97353197fefacf0cfe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 10 Jun 2024 22:16:49 +0200
Subject: [PATCH 06/54] Update the documentation

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../prefer-at-over-subscript-operator.rst     | 22 ++++++++++++++-----
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
index 183175b5966682..42a2100f32582c 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
@@ -3,8 +3,7 @@
 cppcoreguidelines-prefer-at-over-subscript-operator
 =====================================
 
-This check flags all uses of ``operator[]`` on ``std::vector``, ``std::array``, ``std::deque``, ``std::map``, ``std::unordered_map``, and ``std::flat_map`` and suggests to replace it with ``at()``.
-Note that ``std::span`` and ``std::mdspan`` do not support ``at()`` as of C++23, so the use of ``operator[]`` is not flagged.
+This check flags all uses of ``operator[]`` where an equivalent (same parameter and return types) ``at()`` method exists and suggest using that instead.
 
 For example the code
 
@@ -12,10 +11,21 @@ For example the code
   std::array<int, 3> a;
   int b = a[4];
 
-will be replaced by 
+will generate a warning but 
 
 .. code-block:: c++
-  std::vector<int, 3> a;
-  int b = a.at(4);
+  std::unique_ptr<int> a;
+  int b = a[0];
 
-This check enforces the `SL.con.3 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>` guideline.
+will not.
+
+The classes ``std::map``, ``std::unordered_map`` and ``std::flat_map`` are excluded from this check, because for them the subscript operator has a defined behaviour when a key does not exist (inserting a new element).
+
+Options
+-------
+
+.. option:: ExcludeClasses
+
+    Semicolon-delimited list of class names that should additionally be excluded from this check. By default empty. 
+
+This check enforces part of the `SL.con.3 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>` guideline.

>From 0a547491a1f23bc7e47fa25b1e2e891cd2b66200 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 10 Jun 2024 21:43:23 +0200
Subject: [PATCH 07/54] Add remaining tests requested by @PiotrZSL

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../prefer-at-over-subscript-operator.cpp     | 53 +++++++++++++++++--
 1 file changed, 48 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
index 7da6c315569699..cc7088bffeda96 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
@@ -9,6 +9,16 @@ namespace std {
     }
   };
 
+  template<typename T, typename V>
+  struct map {
+    T operator[](unsigned i) {
+      return T{1};
+    }
+    T at(unsigned i) {
+      return T{1};
+    }
+  };
+
   template<typename T>
   struct unique_ptr {
     T operator[](unsigned i) {
@@ -33,6 +43,7 @@ namespace json {
   };
 } // namespace json
 
+struct SubClass : std::array<int, 3> {};
 
 class ExcludedClass1 {
   public:
@@ -62,15 +73,17 @@ std::array<int, 3> a;
 
 auto b = a[0];
 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+
 auto c = a[1+1];
 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
-constexpr int index = 1;
-auto d = a[index];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
 
-int e(int index) {
-  return a[index];
+constexpr int Index = 1;
+auto d = a[Index];
 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+
+int e(int Ind) {
+  return a[Ind];
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
 }
 
 auto f = (&a)->operator[](1);
@@ -87,6 +100,24 @@ auto t = s[0];
 json::node<int> n;
 auto m = n[0];
 
+SubClass Sub;
+auto r = Sub[0];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+
+typedef std::array<int, 3> ar;
+ar BehindDef;
+auto u = BehindDef[0];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+
+template<typename T> int TestTemplate(T t){
+  return t[0];
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+
+}
+
+auto v = TestTemplate<>(a);
+auto w = TestTemplate<>(p);
+
 //explicitely excluded classes / struct / template
 ExcludedClass1 E1;
 auto x1 = E1[0];
@@ -97,3 +128,15 @@ auto x2 = E1[0];
 std::map<int,int> TestMap;
 auto y = TestMap[0];
 
+#define SUBSCRIPT_BEHIND_MARCO(x) a[x]
+#define ARG_BEHIND_MACRO 0
+#define OBJECT_BEHIND_MACRO a
+
+auto m1 = SUBSCRIPT_BEHIND_MARCO(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+
+auto m2 = a[ARG_BEHIND_MACRO];
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+
+auto m3 = OBJECT_BEHIND_MACRO[0];
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]

>From ade7fa4b6c92c8856a94227194e0411114969b32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 10 Jun 2024 22:22:21 +0200
Subject: [PATCH 08/54] Remove unused and rename variables

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../PreferAtOverSubscriptOperatorCheck.cpp                | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
index d7cdbc59d39410..dc036e23e2af15 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
@@ -70,10 +70,10 @@ const CXXMethodDecl *findAlternative(const CXXRecordDecl *MatchedParent,
     if (!SameNumberOfArguments)
       continue;
 
-    for (unsigned a = 0; a < Method->getNumParams(); a++) {
+    for (unsigned ArgInd = 0; ArgInd < Method->getNumParams(); ArgInd++) {
       const bool SameArgType =
-          Method->parameters()[a]->getOriginalType() ==
-          MatchedOperator->parameters()[a]->getOriginalType();
+          Method->parameters()[ArgInd]->getOriginalType() ==
+          MatchedOperator->parameters()[ArgInd]->getOriginalType();
       if (!SameArgType)
         continue;
     }
@@ -98,8 +98,6 @@ void PreferAtOverSubscriptOperatorCheck::registerMatchers(MatchFinder *Finder) {
 
 void PreferAtOverSubscriptOperatorCheck::check(
     const MatchFinder::MatchResult &Result) {
-  const ASTContext &Context = *Result.Context;
-  const SourceManager &Source = Context.getSourceManager();
   const CallExpr *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
   const CXXMethodDecl *MatchedOperator =
       Result.Nodes.getNodeAs<CXXMethodDecl>("operator");

>From ea751a919979d2f96083b78879959fa6c037fa59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Wed, 12 Jun 2024 16:56:40 +0200
Subject: [PATCH 09/54] Update types in
 PreferAtOverSubscriptOperatorCheck::check()

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../PreferAtOverSubscriptOperatorCheck.cpp                 | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
index dc036e23e2af15..0924fda164b4ad 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
@@ -98,11 +98,10 @@ void PreferAtOverSubscriptOperatorCheck::registerMatchers(MatchFinder *Finder) {
 
 void PreferAtOverSubscriptOperatorCheck::check(
     const MatchFinder::MatchResult &Result) {
-  const CallExpr *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
-  const CXXMethodDecl *MatchedOperator =
+  const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
+  const auto *MatchedOperator =
       Result.Nodes.getNodeAs<CXXMethodDecl>("operator");
-  const CXXRecordDecl *MatchedParent =
-      Result.Nodes.getNodeAs<CXXRecordDecl>("parent");
+  const auto *MatchedParent = Result.Nodes.getNodeAs<CXXRecordDecl>("parent");
 
   std::string ClassIdentifier = MatchedParent->getQualifiedNameAsString();
 

>From 152e34f0b2f7a7a00185b5e2ad4bc6123e44dca2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Wed, 12 Jun 2024 17:00:00 +0200
Subject: [PATCH 10/54] Fix length of underline in
 prefer-at-over-subscript-operator.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../cppcoreguidelines/prefer-at-over-subscript-operator.rst     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
index 42a2100f32582c..96c71931ff2a31 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
@@ -1,7 +1,7 @@
 .. title:: clang-tidy - cppcoreguidelines-prefer-at-over-subscript-operator
 
 cppcoreguidelines-prefer-at-over-subscript-operator
-=====================================
+===================================================
 
 This check flags all uses of ``operator[]`` where an equivalent (same parameter and return types) ``at()`` method exists and suggest using that instead.
 

>From 760f9527cd98a8305b8ce855b718915341466f1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Wed, 12 Jun 2024 17:02:33 +0200
Subject: [PATCH 11/54] Enforce 80 char column width in
 prefer-at-over-subscript-operator.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../prefer-at-over-subscript-operator.rst          | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
index 96c71931ff2a31..873564d12dd6b8 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
@@ -3,7 +3,8 @@
 cppcoreguidelines-prefer-at-over-subscript-operator
 ===================================================
 
-This check flags all uses of ``operator[]`` where an equivalent (same parameter and return types) ``at()`` method exists and suggest using that instead.
+This check flags all uses of ``operator[]`` where an equivalent (same parameter
+and return types) ``at()`` method exists and suggest using that instead.
 
 For example the code
 
@@ -19,13 +20,18 @@ will generate a warning but
 
 will not.
 
-The classes ``std::map``, ``std::unordered_map`` and ``std::flat_map`` are excluded from this check, because for them the subscript operator has a defined behaviour when a key does not exist (inserting a new element).
+The classes ``std::map``, ``std::unordered_map`` and ``std::flat_map`` are
+excluded from this check, because for them the subscript operator has a defined
+behaviour when a key does not exist (inserting a new element).
 
 Options
 -------
 
 .. option:: ExcludeClasses
 
-    Semicolon-delimited list of class names that should additionally be excluded from this check. By default empty. 
+    Semicolon-delimited list of class names that should additionally be
+    excluded from this check. By default empty.
 
-This check enforces part of the `SL.con.3 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>` guideline.
+This check enforces part of the `SL.con.3
+<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>`
+guideline.

>From 56eaa1d154b9150f692f12ecb1c53f0fa3fa8e72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Thu, 13 Jun 2024 10:18:58 +0200
Subject: [PATCH 12/54] Synchronise prefer-at-over-subscript-operator.rst with
 ReleaseNotes.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../cppcoreguidelines/prefer-at-over-subscript-operator.rst    | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
index 873564d12dd6b8..7999cd4baeb7c1 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
@@ -3,8 +3,7 @@
 cppcoreguidelines-prefer-at-over-subscript-operator
 ===================================================
 
-This check flags all uses of ``operator[]`` where an equivalent (same parameter
-and return types) ``at()`` method exists and suggest using that instead.
+Flags the unsafe ``operator[]`` and suggests replacing it with ``at()``.
 
 For example the code
 

>From 8a53df6789b5eb047fdff3d9141b710c1988e0ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 17 Jun 2024 12:03:57 +0200
Subject: [PATCH 13/54] Move RUN lines to the top of
 prefer-at-over-subscript-operator.cpp

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../prefer-at-over-subscript-operator.cpp                 | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
index cc7088bffeda96..76b84bf860cb61 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
@@ -1,3 +1,7 @@
+// RUN: %check_clang_tidy %s \
+// RUN: cppcoreguidelines-prefer-at-over-subscript-operator %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-prefer-at-over-subscript-operator.ExcludeClasses: "ExcludedClass1;ExcludedClass2"}}'
+
 namespace std {
   template<typename T, unsigned size>
   struct array {
@@ -65,10 +69,6 @@ class ExcludedClass2 {
     }
 };
 
-
-// RUN: %check_clang_tidy %s \
-// RUN: cppcoreguidelines-prefer-at-over-subscript-operator %t -- \
-// RUN: -config='{CheckOptions: {cppcoreguidelines-prefer-at-over-subscript-operator.ExcludeClasses: "ExcludedClass1;ExcludedClass2"}}'
 std::array<int, 3> a;
 
 auto b = a[0];

>From ee71d8c5b55c8cf882a6623272069cb2633b5cee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 17 Jun 2024 12:05:10 +0200
Subject: [PATCH 14/54] Add an empty lien after each `code-block` in
 prefer-at-over-subscript-operator.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../cppcoreguidelines/prefer-at-over-subscript-operator.rst     | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
index 7999cd4baeb7c1..f3577cb5b15f09 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
@@ -8,12 +8,14 @@ Flags the unsafe ``operator[]`` and suggests replacing it with ``at()``.
 For example the code
 
 .. code-block:: c++
+
   std::array<int, 3> a;
   int b = a[4];
 
 will generate a warning but 
 
 .. code-block:: c++
+
   std::unique_ptr<int> a;
   int b = a[0];
 

>From 8e2cdd1491c7c2af165eeffc494f340304ac9490 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 17 Jun 2024 12:08:56 +0200
Subject: [PATCH 15/54] Use ofClass() instead of hasParent() in
 PreferAtOverSubscriptOperatorCheck.cpp

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp  | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
index 0924fda164b4ad..d047c0b2332d11 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
@@ -90,8 +90,8 @@ void PreferAtOverSubscriptOperatorCheck::registerMatchers(MatchFinder *Finder) {
       callExpr(
           callee(
               cxxMethodDecl(hasOverloadedOperatorName("[]")).bind("operator")),
-          callee(cxxMethodDecl(hasParent(
-              cxxRecordDecl(hasMethod(hasName("at"))).bind("parent")))))
+          callee(cxxMethodDecl(
+              ofClass(cxxRecordDecl(hasMethod(hasName("at"))).bind("parent")))))
           .bind("caller"),
       this);
 }

>From 0caf2207990a1caa57f0b50aff1efd76b9314f1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 17 Jun 2024 12:42:33 +0200
Subject: [PATCH 16/54] Use matchesAnyListedName() in matcher instead of
 explicit std::find() check

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../PreferAtOverSubscriptOperatorCheck.cpp        | 15 +++++----------
 .../prefer-at-over-subscript-operator.cpp         |  2 +-
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
index d047c0b2332d11..82a957241042a1 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
@@ -7,10 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "PreferAtOverSubscriptOperatorCheck.h"
+#include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "llvm/ADT/StringRef.h"
-#include <algorithm>
 #include <numeric>
 
 using namespace clang::ast_matchers;
@@ -18,8 +18,8 @@ using namespace clang::ast_matchers;
 namespace clang::tidy::cppcoreguidelines {
 
 static constexpr std::array<llvm::StringRef, 3> DefaultExclusions = {
-    llvm::StringRef("std::map"), llvm::StringRef("std::unordered_map"),
-    llvm::StringRef("std::flat_map")};
+    llvm::StringRef("::std::map"), llvm::StringRef("::std::unordered_map"),
+    llvm::StringRef("::std::flat_map")};
 
 PreferAtOverSubscriptOperatorCheck::PreferAtOverSubscriptOperatorCheck(
     StringRef Name, ClangTidyContext *Context)
@@ -91,7 +91,8 @@ void PreferAtOverSubscriptOperatorCheck::registerMatchers(MatchFinder *Finder) {
           callee(
               cxxMethodDecl(hasOverloadedOperatorName("[]")).bind("operator")),
           callee(cxxMethodDecl(
-              ofClass(cxxRecordDecl(hasMethod(hasName("at"))).bind("parent")))))
+              ofClass(cxxRecordDecl(hasMethod(hasName("at"))).bind("parent")),
+              unless(matchers::matchesAnyListedName(ExcludedClasses)))))
           .bind("caller"),
       this);
 }
@@ -103,12 +104,6 @@ void PreferAtOverSubscriptOperatorCheck::check(
       Result.Nodes.getNodeAs<CXXMethodDecl>("operator");
   const auto *MatchedParent = Result.Nodes.getNodeAs<CXXRecordDecl>("parent");
 
-  std::string ClassIdentifier = MatchedParent->getQualifiedNameAsString();
-
-  if (std::find(ExcludedClasses.begin(), ExcludedClasses.end(),
-                ClassIdentifier) != ExcludedClasses.end())
-    return;
-
   const CXXMethodDecl *Alternative =
       findAlternative(MatchedParent, MatchedOperator);
   if (!Alternative)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
index 76b84bf860cb61..4ae17688cb9e29 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
@@ -1,6 +1,6 @@
 // RUN: %check_clang_tidy %s \
 // RUN: cppcoreguidelines-prefer-at-over-subscript-operator %t -- \
-// RUN: -config='{CheckOptions: {cppcoreguidelines-prefer-at-over-subscript-operator.ExcludeClasses: "ExcludedClass1;ExcludedClass2"}}'
+// RUN: -config='{CheckOptions: {cppcoreguidelines-prefer-at-over-subscript-operator.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2"}}'
 
 namespace std {
   template<typename T, unsigned size>

>From 567e3d5cf7e33099507cf2779370e830d37b33e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 17 Jun 2024 14:23:35 +0200
Subject: [PATCH 17/54] Match source range of expression in warnings emitted by
 PreferAtOverSubscriptOperatorCheck

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../PreferAtOverSubscriptOperatorCheck.cpp                  | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
index 82a957241042a1..5a5704deae14f2 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
@@ -110,9 +110,11 @@ void PreferAtOverSubscriptOperatorCheck::check(
     return;
 
   diag(MatchedExpr->getBeginLoc(),
-       "found possibly unsafe operator[], consider using at() instead");
+       "found possibly unsafe operator[], consider using at() instead")
+      << MatchedExpr->getSourceRange();
   diag(Alternative->getBeginLoc(), "alternative at() defined here",
-       DiagnosticIDs::Note);
+       DiagnosticIDs::Note)
+      << Alternative->getSourceRange();
 }
 
 } // namespace clang::tidy::cppcoreguidelines

>From 7c011e6856bce47ab71b7714533e00fcc915ad11 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Fri, 21 Jun 2024 10:42:45 +0200
Subject: [PATCH 18/54] PreferAtOverSubscriptOpterator ->
 ProBoundsAvoidUncheckedContainerAccesses

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../cppcoreguidelines/CMakeLists.txt          |  2 +-
 .../CppCoreGuidelinesTidyModule.cpp           |  6 ++---
 ...BoundsAvoidUncheckedContainerAccesses.cpp} | 16 +++++++-----
 ...roBoundsAvoidUncheckedContainerAccesses.h} | 15 ++++++-----
 clang-tools-extra/docs/ReleaseNotes.rst       |  4 +--
 ...ds-avoid-unchecked-container-accesses.rst} |  4 +--
 .../docs/clang-tidy/checks/list.rst           |  2 +-
 ...ds-avoid-unchecked-container-accesses.cpp} | 26 +++++++++----------
 8 files changed, 39 insertions(+), 36 deletions(-)
 rename clang-tools-extra/clang-tidy/cppcoreguidelines/{PreferAtOverSubscriptOperatorCheck.cpp => ProBoundsAvoidUncheckedContainerAccesses.cpp} (88%)
 rename clang-tools-extra/clang-tidy/cppcoreguidelines/{PreferAtOverSubscriptOperatorCheck.h => ProBoundsAvoidUncheckedContainerAccesses.h} (67%)
 rename clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/{prefer-at-over-subscript-operator.rst => pro-bounds-avoid-unchecked-container-accesses.rst} (84%)
 rename clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/{prefer-at-over-subscript-operator.cpp => pro-bounds-avoid-unchecked-container-accesses.cpp} (82%)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
index a9444d33e2f304..c18d81e6111492 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -20,9 +20,9 @@ add_clang_library(clangTidyCppCoreGuidelinesModule STATIC
   NoMallocCheck.cpp
   NoSuspendWithLockCheck.cpp
   OwningMemoryCheck.cpp
-  PreferAtOverSubscriptOperatorCheck.cpp
   PreferMemberInitializerCheck.cpp
   ProBoundsArrayToPointerDecayCheck.cpp
+  ProBoundsAvoidUncheckedContainerAccesses.cpp
   ProBoundsConstantArrayIndexCheck.cpp
   ProBoundsPointerArithmeticCheck.cpp
   ProTypeConstCastCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
index 565a99a865519c..c154f4eec9373a 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -34,9 +34,9 @@
 #include "NoMallocCheck.h"
 #include "NoSuspendWithLockCheck.h"
 #include "OwningMemoryCheck.h"
-#include "PreferAtOverSubscriptOperatorCheck.h"
 #include "PreferMemberInitializerCheck.h"
 #include "ProBoundsArrayToPointerDecayCheck.h"
+#include "ProBoundsAvoidUncheckedContainerAccesses.h"
 #include "ProBoundsConstantArrayIndexCheck.h"
 #include "ProBoundsPointerArithmeticCheck.h"
 #include "ProTypeConstCastCheck.h"
@@ -103,12 +103,12 @@ class CppCoreGuidelinesModule : public ClangTidyModule {
         "cppcoreguidelines-non-private-member-variables-in-classes");
     CheckFactories.registerCheck<OwningMemoryCheck>(
         "cppcoreguidelines-owning-memory");
-    CheckFactories.registerCheck<PreferAtOverSubscriptOperatorCheck>(
-        "cppcoreguidelines-prefer-at-over-subscript-operator");
     CheckFactories.registerCheck<PreferMemberInitializerCheck>(
         "cppcoreguidelines-prefer-member-initializer");
     CheckFactories.registerCheck<ProBoundsArrayToPointerDecayCheck>(
         "cppcoreguidelines-pro-bounds-array-to-pointer-decay");
+    CheckFactories.registerCheck<ProBoundsAvoidUncheckedContainerAccesses>(
+        "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses");
     CheckFactories.registerCheck<ProBoundsConstantArrayIndexCheck>(
         "cppcoreguidelines-pro-bounds-constant-array-index");
     CheckFactories.registerCheck<ProBoundsPointerArithmeticCheck>(
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
similarity index 88%
rename from clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
rename to clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 5a5704deae14f2..19a52d0e565fa4 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -1,4 +1,4 @@
-//===--- PreferAtOverSubscriptOperatorCheck.cpp - clang-tidy --------------===//
+//===--- ProBoundsAvoidUncheckedContainerAccesses.cpp - clang-tidy --------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "PreferAtOverSubscriptOperatorCheck.h"
+#include "ProBoundsAvoidUncheckedContainerAccesses.h"
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -21,8 +21,9 @@ static constexpr std::array<llvm::StringRef, 3> DefaultExclusions = {
     llvm::StringRef("::std::map"), llvm::StringRef("::std::unordered_map"),
     llvm::StringRef("::std::flat_map")};
 
-PreferAtOverSubscriptOperatorCheck::PreferAtOverSubscriptOperatorCheck(
-    StringRef Name, ClangTidyContext *Context)
+ProBoundsAvoidUncheckedContainerAccesses::
+    ProBoundsAvoidUncheckedContainerAccesses(StringRef Name,
+                                             ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context) {
 
   ExcludedClasses = clang::tidy::utils::options::parseStringList(
@@ -31,7 +32,7 @@ PreferAtOverSubscriptOperatorCheck::PreferAtOverSubscriptOperatorCheck(
                          DefaultExclusions.end());
 }
 
-void PreferAtOverSubscriptOperatorCheck::storeOptions(
+void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
     ClangTidyOptions::OptionMap &Opts) {
 
   if (ExcludedClasses.size() == DefaultExclusions.size()) {
@@ -83,7 +84,8 @@ const CXXMethodDecl *findAlternative(const CXXRecordDecl *MatchedParent,
   return static_cast<CXXMethodDecl *>(nullptr);
 }
 
-void PreferAtOverSubscriptOperatorCheck::registerMatchers(MatchFinder *Finder) {
+void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(
+    MatchFinder *Finder) {
   // Need a callExpr here to match CXXOperatorCallExpr ``(&a)->operator[](0)``
   // and CXXMemberCallExpr ``a[0]``.
   Finder->addMatcher(
@@ -97,7 +99,7 @@ void PreferAtOverSubscriptOperatorCheck::registerMatchers(MatchFinder *Finder) {
       this);
 }
 
-void PreferAtOverSubscriptOperatorCheck::check(
+void ProBoundsAvoidUncheckedContainerAccesses::check(
     const MatchFinder::MatchResult &Result) {
   const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
   const auto *MatchedOperator =
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
similarity index 67%
rename from clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h
rename to clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index f2450a7ab34708..33abbef5e82437 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferAtOverSubscriptOperatorCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -1,4 +1,4 @@
-//===--- PreferAtOverSubscriptOperatorCheck.h - clang-tidy ------*- C++ -*-===//
+//===--- ProBoundsAvoidUncheckedContainerAccesses.h - clang-tidy *- C++ -*-===//
 //===--- PreferMemberInitializerCheck.h - clang-tidy ------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERATOVERSUBSCRIPTOPERATORCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERATOVERSUBSCRIPTOPERATORCHECK_H
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_AVOID_UNCHECKED_CONTAINER_ACCESSES_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_AVOID_UNCHECKED_CONTAINER_ACCESSES_H
 
 #include "../ClangTidyCheck.h"
 
@@ -19,10 +19,11 @@ namespace clang::tidy::cppcoreguidelines {
 /// See
 /// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors
 /// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.html
-class PreferAtOverSubscriptOperatorCheck : public ClangTidyCheck {
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.html
+class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck {
 public:
-  PreferAtOverSubscriptOperatorCheck(StringRef Name, ClangTidyContext *Context);
+  ProBoundsAvoidUncheckedContainerAccesses(StringRef Name,
+                                           ClangTidyContext *Context);
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
     return LangOpts.CPlusPlus;
   }
@@ -37,4 +38,4 @@ class PreferAtOverSubscriptOperatorCheck : public ClangTidyCheck {
 
 } // namespace clang::tidy::cppcoreguidelines
 
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERATOVERSUBSCRIPTOPERATORCHECK_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_AVOID_UNCHECKED_CONTAINER_ACCESSES_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 7f65d5f34108c3..0eea1bf86922d3 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -169,8 +169,8 @@ New checks
   Replaces nested ``std::min`` and ``std::max`` calls with an initializer list
   where applicable.
 
-- New :doc:`cppcoreguidelines-prefer-at-over-subscript-operator
-  <clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator>` check.
+- New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
+  <clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>` check.
 
   Flags the unsafe ``operator[]`` and suggests replacing it with ``at()``.
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
similarity index 84%
rename from clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
rename to clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index f3577cb5b15f09..616882738653d0 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-at-over-subscript-operator.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -1,6 +1,6 @@
-.. title:: clang-tidy - cppcoreguidelines-prefer-at-over-subscript-operator
+.. title:: clang-tidy - cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
 
-cppcoreguidelines-prefer-at-over-subscript-operator
+cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
 ===================================================
 
 Flags the unsafe ``operator[]`` and suggests replacing it with ``at()``.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 3b1010b495608b..f85bee79205181 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -194,9 +194,9 @@ Clang-Tidy Checks
    :doc:`cppcoreguidelines-no-malloc <cppcoreguidelines/no-malloc>`,
    :doc:`cppcoreguidelines-no-suspend-with-lock <cppcoreguidelines/no-suspend-with-lock>`,
    :doc:`cppcoreguidelines-owning-memory <cppcoreguidelines/owning-memory>`,
-   :doc:`cppcoreguidelines-prefer-at-over-subscript-operator <cppcoreguidelines/prefer-at-over-subscript-operator>`,
    :doc:`cppcoreguidelines-prefer-member-initializer <cppcoreguidelines/prefer-member-initializer>`, "Yes"
    :doc:`cppcoreguidelines-pro-bounds-array-to-pointer-decay <cppcoreguidelines/pro-bounds-array-to-pointer-decay>`,
+   :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses <cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>`,
    :doc:`cppcoreguidelines-pro-bounds-constant-array-index <cppcoreguidelines/pro-bounds-constant-array-index>`, "Yes"
    :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic <cppcoreguidelines/pro-bounds-pointer-arithmetic>`,
    :doc:`cppcoreguidelines-pro-type-const-cast <cppcoreguidelines/pro-type-const-cast>`,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
similarity index 82%
rename from clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
rename to clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
index 4ae17688cb9e29..1a7a7fba7d8a27 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/prefer-at-over-subscript-operator.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
@@ -1,6 +1,6 @@
 // RUN: %check_clang_tidy %s \
-// RUN: cppcoreguidelines-prefer-at-over-subscript-operator %t -- \
-// RUN: -config='{CheckOptions: {cppcoreguidelines-prefer-at-over-subscript-operator.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2"}}'
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2"}}'
 
 namespace std {
   template<typename T, unsigned size>
@@ -72,22 +72,22 @@ class ExcludedClass2 {
 std::array<int, 3> a;
 
 auto b = a[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto c = a[1+1];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 constexpr int Index = 1;
 auto d = a[Index];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 int e(int Ind) {
   return a[Ind];
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 }
 
 auto f = (&a)->operator[](1);
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto g = a.at(0);
 
@@ -102,16 +102,16 @@ auto m = n[0];
 
 SubClass Sub;
 auto r = Sub[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 typedef std::array<int, 3> ar;
 ar BehindDef;
 auto u = BehindDef[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 template<typename T> int TestTemplate(T t){
   return t[0];
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 }
 
@@ -133,10 +133,10 @@ auto y = TestMap[0];
 #define OBJECT_BEHIND_MACRO a
 
 auto m1 = SUBSCRIPT_BEHIND_MARCO(0);
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto m2 = a[ARG_BEHIND_MACRO];
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto m3 = OBJECT_BEHIND_MACRO[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-prefer-at-over-subscript-operator]
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]

>From 57fb332e4636c83a196ae50790962c72ec327034 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Fri, 21 Jun 2024 10:44:39 +0200
Subject: [PATCH 19/54] Remove extra comment

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index 33abbef5e82437..8fdfd5e9eb518e 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -1,5 +1,4 @@
 //===--- ProBoundsAvoidUncheckedContainerAccesses.h - clang-tidy *- C++ -*-===//
-//===--- PreferMemberInitializerCheck.h - clang-tidy ------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.

>From 7a84658e61bdc64c0e85050cc3b22f41e9662075 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Fri, 21 Jun 2024 10:52:42 +0200
Subject: [PATCH 20/54] Mention bounds safety profile explicitly

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../pro-bounds-avoid-unchecked-container-accesses.rst         | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index 616882738653d0..f39c5171110a01 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -35,4 +35,6 @@ Options
 
 This check enforces part of the `SL.con.3
 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>`
-guideline.
+guideline and is part of the `Bounds Safety (Bounds 4)
+<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-arrayindex>` profile 
+profile from the C++ Core Guidelines.

>From b165f2bc7c1fbf3e6663d342e15c2b1b9c60499a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Fri, 21 Jun 2024 10:55:53 +0200
Subject: [PATCH 21/54] Move paragraph about which rule/profile is being
 implemented above "Options"

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 ...pro-bounds-avoid-unchecked-container-accesses.rst | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index f39c5171110a01..b62ec4fc7b6b5d 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -25,6 +25,12 @@ The classes ``std::map``, ``std::unordered_map`` and ``std::flat_map`` are
 excluded from this check, because for them the subscript operator has a defined
 behaviour when a key does not exist (inserting a new element).
 
+This check enforces part of the `SL.con.3
+<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>`
+guideline and is part of the `Bounds Safety (Bounds 4)
+<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-arrayindex>` profile 
+profile from the C++ Core Guidelines.
+
 Options
 -------
 
@@ -32,9 +38,3 @@ Options
 
     Semicolon-delimited list of class names that should additionally be
     excluded from this check. By default empty.
-
-This check enforces part of the `SL.con.3
-<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>`
-guideline and is part of the `Bounds Safety (Bounds 4)
-<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-arrayindex>` profile 
-profile from the C++ Core Guidelines.

>From 7889607b519990bed9595536145df5e9a89fcc55 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Fri, 21 Jun 2024 11:09:05 +0200
Subject: [PATCH 22/54] Rename variables related to class exclusion mechanism

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 ...oBoundsAvoidUncheckedContainerAccesses.cpp | 26 ++++++++++---------
 ...ProBoundsAvoidUncheckedContainerAccesses.h |  2 +-
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 19a52d0e565fa4..b68583a77ac7f6 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -17,7 +17,7 @@ using namespace clang::ast_matchers;
 
 namespace clang::tidy::cppcoreguidelines {
 
-static constexpr std::array<llvm::StringRef, 3> DefaultExclusions = {
+static constexpr std::array<llvm::StringRef, 3> SubscriptDefaultExclusions = {
     llvm::StringRef("::std::map"), llvm::StringRef("::std::unordered_map"),
     llvm::StringRef("::std::flat_map")};
 
@@ -26,29 +26,30 @@ ProBoundsAvoidUncheckedContainerAccesses::
                                              ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context) {
 
-  ExcludedClasses = clang::tidy::utils::options::parseStringList(
+  SubscriptExcludedClasses = clang::tidy::utils::options::parseStringList(
       Options.get("ExcludeClasses", ""));
-  ExcludedClasses.insert(ExcludedClasses.end(), DefaultExclusions.begin(),
-                         DefaultExclusions.end());
+  SubscriptExcludedClasses.insert(SubscriptExcludedClasses.end(),
+                                  SubscriptDefaultExclusions.begin(),
+                                  SubscriptDefaultExclusions.end());
 }
 
 void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
     ClangTidyOptions::OptionMap &Opts) {
 
-  if (ExcludedClasses.size() == DefaultExclusions.size()) {
+  if (SubscriptExcludedClasses.size() == SubscriptDefaultExclusions.size()) {
     Options.store(Opts, "ExcludeClasses", "");
     return;
   }
 
   // Sum up the sizes of the defaults ( + semicolons), so we can remove them
   // from the saved options
-  size_t DefaultsStringLength =
-      std::transform_reduce(DefaultExclusions.begin(), DefaultExclusions.end(),
-                            DefaultExclusions.size(), std::plus<>(),
-                            [](llvm::StringRef Name) { return Name.size(); });
+  size_t DefaultsStringLength = std::transform_reduce(
+      SubscriptDefaultExclusions.begin(), SubscriptDefaultExclusions.end(),
+      SubscriptDefaultExclusions.size(), std::plus<>(),
+      [](llvm::StringRef Name) { return Name.size(); });
 
-  std::string Serialized =
-      clang::tidy::utils::options::serializeStringList(ExcludedClasses);
+  std::string Serialized = clang::tidy::utils::options::serializeStringList(
+      SubscriptExcludedClasses);
 
   Options.store(Opts, "ExcludeClasses",
                 Serialized.substr(0, Serialized.size() - DefaultsStringLength));
@@ -94,7 +95,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(
               cxxMethodDecl(hasOverloadedOperatorName("[]")).bind("operator")),
           callee(cxxMethodDecl(
               ofClass(cxxRecordDecl(hasMethod(hasName("at"))).bind("parent")),
-              unless(matchers::matchesAnyListedName(ExcludedClasses)))))
+              unless(
+                  matchers::matchesAnyListedName(SubscriptExcludedClasses)))))
           .bind("caller"),
       this);
 }
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index 8fdfd5e9eb518e..3776869e6d42a2 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -32,7 +32,7 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck {
 
 private:
   // A list of class names that are excluded from the warning
-  std::vector<llvm::StringRef> ExcludedClasses;
+  std::vector<llvm::StringRef> SubscriptExcludedClasses;
 };
 
 } // namespace clang::tidy::cppcoreguidelines

>From aafbf4204db47ce03b6fa61c101c2ffe87fb146a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sun, 30 Jun 2024 14:57:07 +0200
Subject: [PATCH 23/54] Remove redundant nullptr cast

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.cpp                | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index b68583a77ac7f6..560ccf3c7ca867 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -82,7 +82,7 @@ const CXXMethodDecl *findAlternative(const CXXRecordDecl *MatchedParent,
 
     return Method;
   }
-  return static_cast<CXXMethodDecl *>(nullptr);
+  return nullptr;
 }
 
 void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(

>From 61f9e519d92940c78c175987150b81dec69eb8e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sun, 30 Jun 2024 15:04:00 +0200
Subject: [PATCH 24/54] Refactor the check's matcher as per 5chmidti's
 suggestion

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 ...oBoundsAvoidUncheckedContainerAccesses.cpp | 24 +++++++++----------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 560ccf3c7ca867..054aa852ca6645 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -55,9 +55,9 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
                 Serialized.substr(0, Serialized.size() - DefaultsStringLength));
 }
 
-const CXXMethodDecl *findAlternative(const CXXRecordDecl *MatchedParent,
-                                     const CXXMethodDecl *MatchedOperator) {
-  for (const CXXMethodDecl *Method : MatchedParent->methods()) {
+const CXXMethodDecl *findAlternative(const CXXMethodDecl *MatchedOperator) {
+  const CXXRecordDecl *Parent = MatchedOperator->getParent();
+  for (const CXXMethodDecl *Method : Parent->methods()) {
     const bool CorrectName = Method->getNameInfo().getAsString() == "at";
     if (!CorrectName)
       continue;
@@ -90,13 +90,13 @@ void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(
   // Need a callExpr here to match CXXOperatorCallExpr ``(&a)->operator[](0)``
   // and CXXMemberCallExpr ``a[0]``.
   Finder->addMatcher(
-      callExpr(
-          callee(
-              cxxMethodDecl(hasOverloadedOperatorName("[]")).bind("operator")),
-          callee(cxxMethodDecl(
-              ofClass(cxxRecordDecl(hasMethod(hasName("at"))).bind("parent")),
-              unless(
-                  matchers::matchesAnyListedName(SubscriptExcludedClasses)))))
+      mapAnyOf(cxxOperatorCallExpr, cxxMemberCallExpr)
+          .with(callee(cxxMethodDecl(hasOverloadedOperatorName("[]"),
+                                     ofClass(cxxRecordDecl(hasMethod(
+                                         cxxMethodDecl(hasName("at"))))),
+                                     unless(matchers::matchesAnyListedName(
+                                         SubscriptExcludedClasses)))
+                           .bind("operator")))
           .bind("caller"),
       this);
 }
@@ -106,10 +106,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
   const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
   const auto *MatchedOperator =
       Result.Nodes.getNodeAs<CXXMethodDecl>("operator");
-  const auto *MatchedParent = Result.Nodes.getNodeAs<CXXRecordDecl>("parent");
 
-  const CXXMethodDecl *Alternative =
-      findAlternative(MatchedParent, MatchedOperator);
+  const CXXMethodDecl *Alternative = findAlternative(MatchedOperator);
   if (!Alternative)
     return;
 

>From d34d3d5b47820c0507810732d71a4cb77b4941b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sun, 30 Jun 2024 15:15:10 +0200
Subject: [PATCH 25/54] Check that alternative is accessible in
 findAlternative() as per @5chmidti's and @PiotrZSL's suggestions

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.cpp  | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 054aa852ca6645..d48b19bb36711e 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -57,7 +57,22 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
 
 const CXXMethodDecl *findAlternative(const CXXMethodDecl *MatchedOperator) {
   const CXXRecordDecl *Parent = MatchedOperator->getParent();
+  const QualType SubscriptThisObjType =
+      MatchedOperator->getFunctionObjectParameterReferenceType();
+
   for (const CXXMethodDecl *Method : Parent->methods()) {
+    // Require 'Method' to be as accessible as 'MatchedOperator' or more
+    if (MatchedOperator->getAccess() < Method->getAccess())
+      continue;
+
+    if (MatchedOperator->isConst() != Method->isConst())
+      continue;
+
+    const QualType AtThisObjType =
+        Method->getFunctionObjectParameterReferenceType();
+    if (SubscriptThisObjType != AtThisObjType)
+      continue;
+
     const bool CorrectName = Method->getNameInfo().getAsString() == "at";
     if (!CorrectName)
       continue;

>From a38a5d8b06ed3328a6aa72af9307f574619e8e8d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sun, 30 Jun 2024 15:28:10 +0200
Subject: [PATCH 26/54] Use upticks when diagnostic messages refer to code

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 ...oBoundsAvoidUncheckedContainerAccesses.cpp |  4 ++--
 ...nds-avoid-unchecked-container-accesses.cpp | 22 +++++++++----------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index d48b19bb36711e..8998cbfc1aeb2e 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -127,9 +127,9 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
     return;
 
   diag(MatchedExpr->getBeginLoc(),
-       "found possibly unsafe operator[], consider using at() instead")
+       "found possibly unsafe 'operator[]', consider using 'at()' instead")
       << MatchedExpr->getSourceRange();
-  diag(Alternative->getBeginLoc(), "alternative at() defined here",
+  diag(Alternative->getBeginLoc(), "alternative 'at()' defined here",
        DiagnosticIDs::Note)
       << Alternative->getSourceRange();
 }
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
index 1a7a7fba7d8a27..9801dbb94ae274 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
@@ -72,22 +72,22 @@ class ExcludedClass2 {
 std::array<int, 3> a;
 
 auto b = a[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto c = a[1+1];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 constexpr int Index = 1;
 auto d = a[Index];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 int e(int Ind) {
   return a[Ind];
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 }
 
 auto f = (&a)->operator[](1);
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto g = a.at(0);
 
@@ -102,16 +102,16 @@ auto m = n[0];
 
 SubClass Sub;
 auto r = Sub[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 typedef std::array<int, 3> ar;
 ar BehindDef;
 auto u = BehindDef[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 template<typename T> int TestTemplate(T t){
   return t[0];
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 }
 
@@ -133,10 +133,10 @@ auto y = TestMap[0];
 #define OBJECT_BEHIND_MACRO a
 
 auto m1 = SUBSCRIPT_BEHIND_MARCO(0);
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto m2 = a[ARG_BEHIND_MACRO];
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto m3 = OBJECT_BEHIND_MACRO[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe operator[], consider using at() instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]

>From 434e277de8bc7762e1b241c308106dff9ef55df9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sun, 30 Jun 2024 15:31:24 +0200
Subject: [PATCH 27/54] Make findAlternative() static

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.cpp               | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 8998cbfc1aeb2e..324a36296aa778 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -55,7 +55,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
                 Serialized.substr(0, Serialized.size() - DefaultsStringLength));
 }
 
-const CXXMethodDecl *findAlternative(const CXXMethodDecl *MatchedOperator) {
+static const CXXMethodDecl *
+findAlternative(const CXXMethodDecl *MatchedOperator) {
   const CXXRecordDecl *Parent = MatchedOperator->getParent();
   const QualType SubscriptThisObjType =
       MatchedOperator->getFunctionObjectParameterReferenceType();

>From 3e27515b5bcca55e7fd7f7351a7f2148a8a29c6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sun, 30 Jun 2024 15:33:49 +0200
Subject: [PATCH 28/54] Move MatchedExpr definition closer to where it's first
 used in ProBoundsAvoidUncheckedContainerAccesses::check()

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.cpp             | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 324a36296aa778..f3dff0769e994e 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -119,14 +119,15 @@ void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(
 
 void ProBoundsAvoidUncheckedContainerAccesses::check(
     const MatchFinder::MatchResult &Result) {
-  const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
   const auto *MatchedOperator =
       Result.Nodes.getNodeAs<CXXMethodDecl>("operator");
-
   const CXXMethodDecl *Alternative = findAlternative(MatchedOperator);
+
   if (!Alternative)
     return;
 
+  const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
+
   diag(MatchedExpr->getBeginLoc(),
        "found possibly unsafe 'operator[]', consider using 'at()' instead")
       << MatchedExpr->getSourceRange();

>From c819bde462bde7bcc6bf6853d8e333cd764cf825 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sun, 30 Jun 2024 15:37:57 +0200
Subject: [PATCH 29/54] Synchronise comment in header file with ReleaseNotes
 and check description

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.h                  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index 3776869e6d42a2..a4770384db0ab2 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -13,7 +13,7 @@
 
 namespace clang::tidy::cppcoreguidelines {
 
-/// Enforce CPP core guidelines SL.con.3
+/// Flags the unsafe ``operator[]`` and suggests replacing it with ``at()``.
 ///
 /// See
 /// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors

>From ff5077fee0458905e7226b47c215f641727158cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 8 Jul 2024 11:05:49 +0200
Subject: [PATCH 30/54] Reword reasoning re: class exclusion in
 pro-bounds-avoid-unchecked-container-accesses.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../pro-bounds-avoid-unchecked-container-accesses.rst           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index b62ec4fc7b6b5d..a2ba12100cbf77 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -22,7 +22,7 @@ will generate a warning but
 will not.
 
 The classes ``std::map``, ``std::unordered_map`` and ``std::flat_map`` are
-excluded from this check, because for them the subscript operator has a defined
+excluded from this check, because their subscript operator has a defined
 behaviour when a key does not exist (inserting a new element).
 
 This check enforces part of the `SL.con.3

>From 70638ef43a9cd5ad515e548862674c066fe4d6af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 8 Jul 2024 11:15:32 +0200
Subject: [PATCH 31/54] Replace array with container
 inpro-bounds-avoid-unchecked-container-accesses.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../pro-bounds-avoid-unchecked-container-accesses.rst           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index a2ba12100cbf77..1221c38f238838 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -9,7 +9,7 @@ For example the code
 
 .. code-block:: c++
 
-  std::array<int, 3> a;
+  std::vector<int> a;
   int b = a[4];
 
 will generate a warning but 

>From 650154a8296dd65b07eca394d857de25e3e2cbfd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 8 Jul 2024 11:17:39 +0200
Subject: [PATCH 32/54] Update unique_ptr example in
 pro-bounds-avoid-unchecked-container-accesses.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../pro-bounds-avoid-unchecked-container-accesses.rst           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index 1221c38f238838..4bc91adb2ee62a 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -16,7 +16,7 @@ will generate a warning but
 
 .. code-block:: c++
 
-  std::unique_ptr<int> a;
+  std::unique_ptr<vector> a;
   int b = a[0];
 
 will not.

>From 8f0fcccf6a023e4f2fa9bd2252405e76cbe2c512 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 8 Jul 2024 12:15:00 +0200
Subject: [PATCH 33/54] Remove outdated comment in
 ProBoundsAvoidUncheckedContainerAccess.cpp

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.cpp                | 2 --
 1 file changed, 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index f3dff0769e994e..81cb943082a687 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -103,8 +103,6 @@ findAlternative(const CXXMethodDecl *MatchedOperator) {
 
 void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(
     MatchFinder *Finder) {
-  // Need a callExpr here to match CXXOperatorCallExpr ``(&a)->operator[](0)``
-  // and CXXMemberCallExpr ``a[0]``.
   Finder->addMatcher(
       mapAnyOf(cxxOperatorCallExpr, cxxMemberCallExpr)
           .with(callee(cxxMethodDecl(hasOverloadedOperatorName("[]"),

>From 2a2b0a87df4365ca37eaa64d44bcf09d95a9bec9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 8 Jul 2024 12:21:27 +0200
Subject: [PATCH 34/54] Use TK_IgnoreUnlessSpelledInSource as traversal kind

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h      | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
index a583cc78b2c547..6034b1542108e1 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
@@ -32,6 +32,10 @@ class ProBoundsConstantArrayIndexCheck : public ClangTidyCheck {
                            Preprocessor *ModuleExpanderPP) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  std::optional<TraversalKind> getCheckTraversalKind() const override {
+    return TK_IgnoreUnlessSpelledInSource;
+  }
+
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
 };
 

>From b60e202e35f420431f21c275ba86fb5a1cff775a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Thu, 25 Jul 2024 13:30:42 +0200
Subject: [PATCH 35/54] Revert "Use TK_IgnoreUnlessSpelledInSource as traversal
 kind"

This reverts commit ed2076750349881a2613816746fadd792212bb01.

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h      | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
index 6034b1542108e1..a583cc78b2c547 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
@@ -32,10 +32,6 @@ class ProBoundsConstantArrayIndexCheck : public ClangTidyCheck {
                            Preprocessor *ModuleExpanderPP) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
-  std::optional<TraversalKind> getCheckTraversalKind() const override {
-    return TK_IgnoreUnlessSpelledInSource;
-  }
-
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
 };
 

>From 49671becfec0bbf975b4324afdd7da488536e9e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Fri, 2 Aug 2024 16:44:02 +0200
Subject: [PATCH 36/54] Add template test with std::map as an argument

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../pro-bounds-avoid-unchecked-container-accesses.cpp    | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
index 9801dbb94ae274..447b4d1bed195a 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
@@ -115,9 +115,15 @@ template<typename T> int TestTemplate(T t){
 
 }
 
+
 auto v = TestTemplate<>(a);
 auto w = TestTemplate<>(p);
 
+std::map<int,int> TestMap;
+auto x = TestTemplate<>(TestMap);
+
+auto y = TestMap[0];
+
 //explicitely excluded classes / struct / template
 ExcludedClass1 E1;
 auto x1 = E1[0];
@@ -125,9 +131,6 @@ auto x1 = E1[0];
 ExcludedClass2 E2;
 auto x2 = E1[0];
 
-std::map<int,int> TestMap;
-auto y = TestMap[0];
-
 #define SUBSCRIPT_BEHIND_MARCO(x) a[x]
 #define ARG_BEHIND_MACRO 0
 #define OBJECT_BEHIND_MACRO a

>From 84f598ccd47ecc0662900809a74b5e313bbfecc1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Fri, 2 Aug 2024 16:53:35 +0200
Subject: [PATCH 37/54] Use getNameInfo().getSourceRange() instead of
 getSourceRange() when printing the location of the alternative

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.cpp                | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 81cb943082a687..6435277a020f5a 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -131,7 +131,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
       << MatchedExpr->getSourceRange();
   diag(Alternative->getBeginLoc(), "alternative 'at()' defined here",
        DiagnosticIDs::Note)
-      << Alternative->getSourceRange();
+      << Alternative->getNameInfo().getSourceRange();
 }
 
 } // namespace clang::tidy::cppcoreguidelines

>From 89f3bafeb7b91e8d07cd53cfa4bef4dd85d033dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 3 Aug 2024 22:04:25 +0200
Subject: [PATCH 38/54] Replace use of Method->getNameInfo().getAsString() with
 Method->getName()

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.cpp              | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 6435277a020f5a..c0f1fbd7923758 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -74,8 +74,8 @@ findAlternative(const CXXMethodDecl *MatchedOperator) {
     if (SubscriptThisObjType != AtThisObjType)
       continue;
 
-    const bool CorrectName = Method->getNameInfo().getAsString() == "at";
-    if (!CorrectName)
+    if (!Method->getNameInfo().getName().isIdentifier() ||
+        Method->getName() != "at")
       continue;
 
     const bool SameReturnType =

>From b4bb927d503f60f0ba6d7c18a7dd7a88ff318979 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Thu, 8 Aug 2024 11:33:36 +0200
Subject: [PATCH 39/54] Add TODO comment re: findAlternative()'s capabilities
 in class hierarchies

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.cpp               | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index c0f1fbd7923758..2bd4b2b96506a2 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -55,6 +55,9 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
                 Serialized.substr(0, Serialized.size() - DefaultsStringLength));
 }
 
+// TODO: if at() is defined in another class in the class hierarchy of the class
+// that defines the operator[] we matched on, findAlternative() will not detect
+// it.
 static const CXXMethodDecl *
 findAlternative(const CXXMethodDecl *MatchedOperator) {
   const CXXRecordDecl *Parent = MatchedOperator->getParent();

>From 3cc904a870614d3c43ae94aa83b96650a0cd2000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Thu, 8 Aug 2024 12:52:25 +0200
Subject: [PATCH 40/54] Reduce size of SourceRange when printing warnings

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.cpp              | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 2bd4b2b96506a2..77798ccebdf897 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -129,9 +129,9 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
 
   const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
 
-  diag(MatchedExpr->getBeginLoc(),
+  diag(MatchedExpr->getCallee()->getBeginLoc(),
        "found possibly unsafe 'operator[]', consider using 'at()' instead")
-      << MatchedExpr->getSourceRange();
+      << MatchedExpr->getCallee()->getSourceRange();
   diag(Alternative->getBeginLoc(), "alternative 'at()' defined here",
        DiagnosticIDs::Note)
       << Alternative->getNameInfo().getSourceRange();

>From 8e49cc88b32257bccc475baf00b0691184bf959d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Thu, 8 Aug 2024 16:09:34 +0200
Subject: [PATCH 41/54] Add customizable fixit suggestions

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 ...oBoundsAvoidUncheckedContainerAccesses.cpp | 142 ++++++++++++++++--
 ...ProBoundsAvoidUncheckedContainerAccesses.h |  21 ++-
 2 files changed, 145 insertions(+), 18 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 77798ccebdf897..09950ca516f585 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -31,11 +31,15 @@ ProBoundsAvoidUncheckedContainerAccesses::
   SubscriptExcludedClasses.insert(SubscriptExcludedClasses.end(),
                                   SubscriptDefaultExclusions.begin(),
                                   SubscriptDefaultExclusions.end());
+  SubscriptFixMode = Options.get("SubscriptFixMode", None);
+  SubscriptFixFunction = Options.get("SubscriptFixFunction", "gsl::at");
 }
 
 void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
     ClangTidyOptions::OptionMap &Opts) {
 
+  Options.store(Opts, "SubscriptFixFunction", SubscriptFixFunction);
+  Options.store(Opts, "SubscriptFixMode", SubscriptFixMode);
   if (SubscriptExcludedClasses.size() == SubscriptDefaultExclusions.size()) {
     Options.store(Opts, "ExcludeClasses", "");
     return;
@@ -51,7 +55,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
   std::string Serialized = clang::tidy::utils::options::serializeStringList(
       SubscriptExcludedClasses);
 
-  Options.store(Opts, "ExcludeClasses",
+  Options.store(Opts, "SubscriptExcludeClasses",
                 Serialized.substr(0, Serialized.size() - DefaultsStringLength));
 }
 
@@ -59,7 +63,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
 // that defines the operator[] we matched on, findAlternative() will not detect
 // it.
 static const CXXMethodDecl *
-findAlternative(const CXXMethodDecl *MatchedOperator) {
+findAlternativeAt(const CXXMethodDecl *MatchedOperator) {
   const CXXRecordDecl *Parent = MatchedOperator->getParent();
   const QualType SubscriptThisObjType =
       MatchedOperator->getFunctionObjectParameterReferenceType();
@@ -109,8 +113,6 @@ void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(
   Finder->addMatcher(
       mapAnyOf(cxxOperatorCallExpr, cxxMemberCallExpr)
           .with(callee(cxxMethodDecl(hasOverloadedOperatorName("[]"),
-                                     ofClass(cxxRecordDecl(hasMethod(
-                                         cxxMethodDecl(hasName("at"))))),
                                      unless(matchers::matchesAnyListedName(
                                          SubscriptExcludedClasses)))
                            .bind("operator")))
@@ -120,21 +122,129 @@ void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(
 
 void ProBoundsAvoidUncheckedContainerAccesses::check(
     const MatchFinder::MatchResult &Result) {
-  const auto *MatchedOperator =
-      Result.Nodes.getNodeAs<CXXMethodDecl>("operator");
-  const CXXMethodDecl *Alternative = findAlternative(MatchedOperator);
-
-  if (!Alternative)
-    return;
 
   const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
 
-  diag(MatchedExpr->getCallee()->getBeginLoc(),
-       "found possibly unsafe 'operator[]', consider using 'at()' instead")
-      << MatchedExpr->getCallee()->getSourceRange();
-  diag(Alternative->getBeginLoc(), "alternative 'at()' defined here",
-       DiagnosticIDs::Note)
-      << Alternative->getNameInfo().getSourceRange();
+  if (SubscriptFixMode == None) {
+    diag(MatchedExpr->getCallee()->getBeginLoc(),
+         "possibly unsafe 'operator[]', consider bound-safe alternatives")
+        << MatchedExpr->getCallee()->getSourceRange();
+    return;
+  }
+
+  if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(MatchedExpr)) {
+    // Case: a[i]
+    auto LeftBracket = SourceRange(OCE->getCallee()->getBeginLoc(),
+                                   OCE->getCallee()->getBeginLoc());
+    auto RightBracket =
+        SourceRange(OCE->getOperatorLoc(), OCE->getOperatorLoc());
+
+    if (SubscriptFixMode == At) {
+      // Case: a[i] => a.at(i)
+      const auto *MatchedOperator =
+          Result.Nodes.getNodeAs<CXXMethodDecl>("operator");
+      const CXXMethodDecl *Alternative = findAlternativeAt(MatchedOperator);
+
+      if (!Alternative) {
+        diag(MatchedExpr->getCallee()->getBeginLoc(),
+             "possibly unsafe 'operator[]', consider "
+             "bound-safe alternatives")
+            << MatchedExpr->getCallee()->getSourceRange();
+        return;
+      }
+
+      diag(MatchedExpr->getCallee()->getBeginLoc(),
+           "possibly unsafe 'operator[]', consider "
+           "bound-safe alternative 'at()'")
+          << MatchedExpr->getCallee()->getSourceRange()
+          << FixItHint::CreateReplacement(LeftBracket, ".at(")
+          << FixItHint::CreateReplacement(RightBracket, ")");
+
+      diag(Alternative->getBeginLoc(), "viable 'at()' is defined here",
+           DiagnosticIDs::Note)
+          << Alternative->getNameInfo().getSourceRange();
+
+    } else if (SubscriptFixMode == Function) {
+      // Case: a[i] => f(a, i)
+      diag(MatchedExpr->getCallee()->getBeginLoc(),
+           "possibly unsafe 'operator[]', use safe function '" +
+               SubscriptFixFunction.str() + "()' instead")
+          << MatchedExpr->getCallee()->getSourceRange()
+          << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(),
+                                        SubscriptFixFunction.str() + "(")
+          // Since C++23, the subscript operator may also be called without an
+          // argument, which makes the following distinction necessary
+          << (MatchedExpr->getDirectCallee()->getNumParams() > 0
+                  ? FixItHint::CreateReplacement(LeftBracket, ", ")
+                  : FixItHint::CreateRemoval(LeftBracket))
+          << FixItHint::CreateReplacement(RightBracket, ")");
+    }
+  } else if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(MatchedExpr)) {
+    // Case: a.operator[](i) or a->operator[](i)
+    const auto *Callee = dyn_cast<MemberExpr>(MCE->getCallee());
+
+    if (SubscriptFixMode == At) {
+      // Cases: a.operator[](i) => a.at(i) and a->operator[](i) => a->at(i)
+
+      const auto *MatchedOperator =
+          Result.Nodes.getNodeAs<CXXMethodDecl>("operator");
+
+      const CXXMethodDecl *Alternative = findAlternativeAt(MatchedOperator);
+      if (!Alternative) {
+        diag(Callee->getBeginLoc(), "possibly unsafe 'operator[]', consider "
+                                    "bound-safe alternative 'at()'")
+            << Callee->getSourceRange();
+        return;
+      }
+      diag(MatchedExpr->getCallee()->getBeginLoc(),
+           "possibly unsafe 'operator[]', consider "
+           "bound-safe alternative 'at()'")
+          << FixItHint::CreateReplacement(
+                 SourceRange(Callee->getMemberLoc(), Callee->getEndLoc()),
+                 "at");
+
+      diag(Alternative->getBeginLoc(), "viable 'at()' defined here",
+           DiagnosticIDs::Note)
+          << Alternative->getNameInfo().getSourceRange();
+
+    } else if (SubscriptFixMode == Function) {
+      // Cases: a.operator[](i) => f(a, i) and a->operator[](i) => f(*a, i)
+      const auto *Callee = dyn_cast<MemberExpr>(MCE->getCallee());
+      std::string BeginInsertion = SubscriptFixFunction.str() + "(";
+
+      if (Callee->isArrow())
+        BeginInsertion += "*";
+
+      diag(Callee->getBeginLoc(),
+           "possibly unsafe 'operator[]', use safe function '" +
+               SubscriptFixFunction.str() + "()' instead")
+          << Callee->getSourceRange()
+          << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(),
+                                        BeginInsertion)
+          // Since C++23, the subscript operator may also be called without an
+          // argument, which makes the following distinction necessary
+          << ((MCE->getMethodDecl()->getNumNonObjectParams() > 0)
+                  ? FixItHint::CreateReplacement(
+                        SourceRange(
+                            Callee->getOperatorLoc(),
+                            MCE->getArg(0)->getBeginLoc().getLocWithOffset(-1)),
+                        ", ")
+                  : FixItHint::CreateRemoval(
+                        SourceRange(Callee->getOperatorLoc(),
+                                    MCE->getRParenLoc().getLocWithOffset(-1))));
+    }
+  }
 }
 
 } // namespace clang::tidy::cppcoreguidelines
+
+namespace clang::tidy {
+using P = cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses;
+
+llvm::ArrayRef<std::pair<P::SubscriptFixModes, StringRef>>
+OptionEnumMapping<P::SubscriptFixModes>::getEnumMapping() {
+  static constexpr std::pair<P::SubscriptFixModes, StringRef> Mapping[] = {
+      {P::None, "None"}, {P::At, "at"}, {P::Function, "function"}};
+  return {Mapping};
+}
+} // namespace clang::tidy
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index a4770384db0ab2..aa2d3e94d04678 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -13,7 +13,8 @@
 
 namespace clang::tidy::cppcoreguidelines {
 
-/// Flags the unsafe ``operator[]`` and suggests replacing it with ``at()``.
+/// Flags the unsafe ``operator[]``. Can suggests fixing it with ``at()`` or a
+/// user-provided function.
 ///
 /// See
 /// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors
@@ -30,11 +31,27 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck {
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
 
+  enum SubscriptFixModes { None, At, Function };
+
 private:
   // A list of class names that are excluded from the warning
   std::vector<llvm::StringRef> SubscriptExcludedClasses;
+  // Setting which fix to suggest
+  SubscriptFixModes SubscriptFixMode;
+  llvm::StringRef SubscriptFixFunction;
 };
-
 } // namespace clang::tidy::cppcoreguidelines
 
+namespace clang::tidy {
+template <>
+struct OptionEnumMapping<
+    cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses::
+        SubscriptFixModes> {
+  static ArrayRef<
+      std::pair<cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses::
+                    SubscriptFixModes,
+                StringRef>>
+  getEnumMapping();
+};
+} // namespace clang::tidy
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_AVOID_UNCHECKED_CONTAINER_ACCESSES_H

>From 89559cf4d55564074071907242e0ba3510b3d9cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Thu, 8 Aug 2024 16:15:41 +0200
Subject: [PATCH 42/54] Document customizable fixit suggestions

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 clang-tools-extra/docs/ReleaseNotes.rst       |  3 ++-
 ...nds-avoid-unchecked-container-accesses.rst | 21 ++++++++++++++-----
 .../docs/clang-tidy/checks/list.rst           |  2 +-
 3 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 0eea1bf86922d3..dff21cb961be6b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -172,7 +172,8 @@ New checks
 - New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
   <clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>` check.
 
-  Flags the unsafe ``operator[]`` and suggests replacing it with ``at()``.
+  Flags the unsafe ``operator[]``. Can suggests fixing it with ``at()`` or a
+  user-provided function.
 
 New check aliases
 ^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index 4bc91adb2ee62a..62540f106e4bdc 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -1,9 +1,10 @@
 .. title:: clang-tidy - cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
 
 cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
-===================================================
+===============================================================
 
-Flags the unsafe ``operator[]`` and suggests replacing it with ``at()``.
+Flags the unsafe ``operator[]``. Can suggests fixing it with ``at()`` or a
+user-provided function.
 
 For example the code
 
@@ -19,7 +20,7 @@ will generate a warning but
   std::unique_ptr<vector> a;
   int b = a[0];
 
-will not.
+will generate a warning.
 
 The classes ``std::map``, ``std::unordered_map`` and ``std::flat_map`` are
 excluded from this check, because their subscript operator has a defined
@@ -28,13 +29,23 @@ behaviour when a key does not exist (inserting a new element).
 This check enforces part of the `SL.con.3
 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>`
 guideline and is part of the `Bounds Safety (Bounds 4)
-<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-arrayindex>` profile 
+<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-arrayindex>`
 profile from the C++ Core Guidelines.
 
 Options
 -------
 
-.. option:: ExcludeClasses
+.. option:: SubscriptExcludeClasses
 
     Semicolon-delimited list of class names that should additionally be
     excluded from this check. By default empty.
+
+.. option:: SubscriptFixMode
+
+    Determines what fixes are suggested. Either `None` (default), `at` (use 
+    ``a.at(index)`` if a fitting function exists ) or `function` (use a 
+    function ``f(a, index)``).
+
+.. option:: SubscriptFixFunction
+
+    The function to use in the `function` mode. ``gsl::at`` by default.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index f85bee79205181..9a18f450702458 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -196,7 +196,7 @@ Clang-Tidy Checks
    :doc:`cppcoreguidelines-owning-memory <cppcoreguidelines/owning-memory>`,
    :doc:`cppcoreguidelines-prefer-member-initializer <cppcoreguidelines/prefer-member-initializer>`, "Yes"
    :doc:`cppcoreguidelines-pro-bounds-array-to-pointer-decay <cppcoreguidelines/pro-bounds-array-to-pointer-decay>`,
-   :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses <cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>`,
+   :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses <cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>`, "Yes"
    :doc:`cppcoreguidelines-pro-bounds-constant-array-index <cppcoreguidelines/pro-bounds-constant-array-index>`, "Yes"
    :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic <cppcoreguidelines/pro-bounds-pointer-arithmetic>`,
    :doc:`cppcoreguidelines-pro-type-const-cast <cppcoreguidelines/pro-type-const-cast>`,

>From c06b11eed00bb6f478c19beb5bf598cdd34bc442 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Thu, 8 Aug 2024 16:10:46 +0200
Subject: [PATCH 43/54] Test customizable fixit suggestions

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 ...nds-avoid-unchecked-container-accesses.cpp | 124 +++++++++++++++---
 1 file changed, 103 insertions(+), 21 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
index 447b4d1bed195a..b7f5e9ba3e5cb8 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
@@ -1,16 +1,33 @@
-// RUN: %check_clang_tidy %s \
+// RUN: %check_clang_tidy -std=c++2b -check-suffix=DEFAULT %s \
 // RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
 // RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2"}}'
 
+// RUN: %check_clang_tidy -std=c++2b -check-suffix=AT %s \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2", \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.SubscriptFixMode: at}}'
+
+// RUN: %check_clang_tidy -std=c++2b -check-suffix=FUNC %s \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2", \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.SubscriptFixMode: function, \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.SubscriptFixFunction: "f"}}'
+
 namespace std {
   template<typename T, unsigned size>
   struct array {
     T operator[](unsigned i) {
       return T{1};
     }
+    T operator[]() {
+      return T{1};
+    }
     T at(unsigned i) {
       return T{1};
     }
+    T at() {
+      return T{1};
+    }
   };
 
   template<typename T, typename V>
@@ -69,49 +86,96 @@ class ExcludedClass2 {
     }
 };
 
+template<class T> int f(T, unsigned){ return 0;}
+template<class T> int f(T){ return 0;}
+
 std::array<int, 3> a;
 
 auto b = a[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto b = a.at(0);
+// CHECK-FIXES-FUNC: auto b = f(a, 0);
+
+auto b23 = a[];
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto b23 = a.at();
+// CHECK-FIXES-FUNC: auto b23 = f(a);
+
 
 auto c = a[1+1];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto c = a.at(1+1);
+// CHECK-FIXES-FUNC: auto c = f(a, 1+1);
 
 constexpr int Index = 1;
 auto d = a[Index];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto d = a.at(Index);
+// CHECK-FIXES-FUNC: auto d = f(a, Index);
 
 int e(int Ind) {
   return a[Ind];
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+  // CHECK-FIXES-AT: return a.at(Ind);
+  // CHECK-FIXES-FUNC: return f(a, Ind);
 }
 
-auto f = (&a)->operator[](1);
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+auto fa = (&a)->operator[](1);
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto fa = (&a)->at(1);
+// CHECK-FIXES-FUNC: auto fa = f(*(&a), 1);
+
+auto fd = a.operator[](1);
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto fd = a.at(1);
+// CHECK-FIXES-FUNC: auto fd = f(a, 1);
+//
+auto fa23 = (&a)->operator[]();
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto fa23 = (&a)->at();
+// CHECK-FIXES-FUNC: auto fa23 = f(*(&a));
+
+auto fd23 = a.operator[]();
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto fd23 = a.at();
+// CHECK-FIXES-FUNC: auto fd23 = f(a);
 
 auto g = a.at(0);
 
 std::unique_ptr<int> p;
 auto q = p[0];
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto q = p[0];
+// CHECK-FIXES-FUNC: auto q = f(p, 0);
 
 std::span<int> s;
 auto t = s[0];
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto t = s[0];
+// CHECK-FIXES-FUNC: auto t = f(s, 0);
 
 json::node<int> n;
 auto m = n[0];
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto m = n[0];
+// CHECK-FIXES-FUNC: auto m = f(n, 0);
 
 SubClass Sub;
 auto r = Sub[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto r = Sub.at(0);
+// CHECK-FIXES-FUNC: auto r = f(Sub, 0);
 
 typedef std::array<int, 3> ar;
 ar BehindDef;
 auto u = BehindDef[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:19: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto u = BehindDef.at(0);
+// CHECK-FIXES-FUNC: auto u = f(BehindDef, 0);
 
 template<typename T> int TestTemplate(T t){
   return t[0];
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:10: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 }
 
@@ -119,27 +183,45 @@ template<typename T> int TestTemplate(T t){
 auto v = TestTemplate<>(a);
 auto w = TestTemplate<>(p);
 
-std::map<int,int> TestMap;
-auto x = TestTemplate<>(TestMap);
-
-auto y = TestMap[0];
-
-//explicitely excluded classes / struct / template
+//excluded classes 
 ExcludedClass1 E1;
 auto x1 = E1[0];
 
 ExcludedClass2 E2;
 auto x2 = E1[0];
 
-#define SUBSCRIPT_BEHIND_MARCO(x) a[x]
+std::map<int,int> TestMap;
+auto y = TestMap[0];
+
+#define SUBSCRIPT_BEHIND_MACRO(x) a[x]
 #define ARG_BEHIND_MACRO 0
 #define OBJECT_BEHIND_MACRO a
 
-auto m1 = SUBSCRIPT_BEHIND_MARCO(0);
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+auto m1 = SUBSCRIPT_BEHIND_MACRO(0);
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto m2 = a[ARG_BEHIND_MACRO];
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto m2 = a.at(ARG_BEHIND_MACRO);
+// CHECK-FIXES-FUNC: auto m2 = f(a, ARG_BEHIND_MACRO);
 
 auto m3 = OBJECT_BEHIND_MACRO[0];
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: found possibly unsafe 'operator[]', consider using 'at()' instead [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:30: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto m3 = OBJECT_BEHIND_MACRO.at(0);
+// CHECK-FIXES-FUNC: auto m3 = f(OBJECT_BEHIND_MACRO, 0);
+
+// Check that spacing does not invalidate the fixes 
+std::array<int , 3> longname;
+
+auto z1 = longname   [    0    ]  ;
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:22: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto z1 = longname   .at(    0    )  ;
+// CHECK-FIXES-FUNC: auto z1 = f(longname   ,     0    )  ;
+auto z2 = longname   . operator[]   ( 0 );
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto z2 = longname   . at   ( 0 );
+// CHECK-FIXES-FUNC: auto z2 = f(longname   ,  0 );
+auto z3 = (&longname)   -> operator[]   ( 0 );
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT: auto z3 = (&longname)   -> at   ( 0 );
+// CHECK-FIXES-FUNC: auto z3 = f(*(&longname)   ,  0 );

>From 462d0fd34fee6180c438630bfa305c5e27c68008 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 26 Oct 2024 20:43:04 +0200
Subject: [PATCH 44/54] Remove rebase artifacts in ReleaseNotes.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 clang-tools-extra/docs/ReleaseNotes.rst | 56 -------------------------
 1 file changed, 56 deletions(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index dff21cb961be6b..8c1502089071a5 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -113,62 +113,6 @@ Improvements to clang-tidy
 New checks
 ^^^^^^^^^^
 
-- New :doc:`bugprone-bitwise-pointer-cast
-  <clang-tidy/checks/bugprone/bitwise-pointer-cast>` check.
-
-  Warns about code that tries to cast between pointers by means of
-  ``std::bit_cast`` or ``memcpy``.
-
-- New :doc:`bugprone-nondeterministic-pointer-iteration-order
-  <clang-tidy/checks/bugprone/nondeterministic-pointer-iteration-order>`
-  check.
-
-  Finds nondeterministic usages of pointers in unordered containers.
-
-- New :doc:`bugprone-tagged-union-member-count
-  <clang-tidy/checks/bugprone/tagged-union-member-count>` check.
-
-  Gives warnings for tagged unions, where the number of tags is
-  different from the number of data members inside the union.
-
-- New :doc:`portability-template-virtual-member-function
-  <clang-tidy/checks/portability/template-virtual-member-function>` check.
-
-  Finds cases when an uninstantiated virtual member function in a template class 
-  causes cross-compiler incompatibility.
-
-- New :doc:`bugprone-crtp-constructor-accessibility
-  <clang-tidy/checks/bugprone/crtp-constructor-accessibility>` check.
-
-  Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP
-  can be constructed outside itself and the derived class.
-
-- New :doc:`bugprone-return-const-ref-from-parameter
-  <clang-tidy/checks/bugprone/return-const-ref-from-parameter>` check.
-
-  Detects return statements that return a constant reference parameter as constant
-  reference. This may cause use-after-free errors if the caller uses xvalues as
-  arguments.
-
-- New :doc:`bugprone-suspicious-stringview-data-usage
-  <clang-tidy/checks/bugprone/suspicious-stringview-data-usage>` check.
-
-  Identifies suspicious usages of ``std::string_view::data()`` that could lead
-  to reading out-of-bounds data due to inadequate or incorrect string null
-  termination.
-
-- New :doc:`misc-use-internal-linkage
-  <clang-tidy/checks/misc/use-internal-linkage>` check.
-
-  Detects variables and functions that can be marked as static or moved into
-  an anonymous namespace to enforce internal linkage.
-
-- New :doc:`modernize-min-max-use-initializer-list
-  <clang-tidy/checks/modernize/min-max-use-initializer-list>` check.
-
-  Replaces nested ``std::min`` and ``std::max`` calls with an initializer list
-  where applicable.
-
 - New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
   <clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>` check.
 

>From 83c72e20e6c0ff17aec0d5bd70286b4a84b4b848 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 26 Oct 2024 20:56:56 +0200
Subject: [PATCH 45/54] Update one-sentence description of
 `cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses` check

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../ProBoundsAvoidUncheckedContainerAccesses.h                | 4 ++--
 clang-tools-extra/docs/ReleaseNotes.rst                       | 4 ++--
 .../pro-bounds-avoid-unchecked-container-accesses.rst         | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index aa2d3e94d04678..6e7f28708773e5 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -13,8 +13,8 @@
 
 namespace clang::tidy::cppcoreguidelines {
 
-/// Flags the unsafe ``operator[]``. Can suggests fixing it with ``at()`` or a
-/// user-provided function.
+/// Flags calls to operator[] in STL containers and suggests replacing it with
+/// safe alternatives.
 ///
 /// See
 /// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 8c1502089071a5..c1220cc19c9a03 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -116,8 +116,8 @@ New checks
 - New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
   <clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>` check.
 
-  Flags the unsafe ``operator[]``. Can suggests fixing it with ``at()`` or a
-  user-provided function.
+  Flags calls to operator[] in STL containers and suggests replacing it with
+  safe alternatives.
 
 New check aliases
 ^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index 62540f106e4bdc..3b546446bb065d 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -3,8 +3,8 @@
 cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
 ===============================================================
 
-Flags the unsafe ``operator[]``. Can suggests fixing it with ``at()`` or a
-user-provided function.
+Flags calls to operator[] in STL containers and suggests replacing it with
+safe alternatives.
 
 For example the code
 

>From 580e204401bb60b2487e4e24aead97f175c96a8c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 26 Oct 2024 21:01:59 +0200
Subject: [PATCH 46/54] Format description of the
 `cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses` in
 ReleaseNotes.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 clang-tools-extra/docs/ReleaseNotes.rst | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index c1220cc19c9a03..36f5999b7d610d 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -114,7 +114,8 @@ New checks
 ^^^^^^^^^^
 
 - New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
-  <clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>` check.
+  <clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>`
+  check.
 
   Flags calls to operator[] in STL containers and suggests replacing it with
   safe alternatives.

>From 2b98ceaceaff4a36fa8eaeb1856b72777e993f81 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 26 Oct 2024 21:06:26 +0200
Subject: [PATCH 47/54] Generalise description of excluded classes in
 `pro-bounds-avoid-unchecked-container-accesses.rst`

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../pro-bounds-avoid-unchecked-container-accesses.rst        | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index 3b546446bb065d..b677e1d34e4145 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -22,9 +22,8 @@ will generate a warning but
 
 will generate a warning.
 
-The classes ``std::map``, ``std::unordered_map`` and ``std::flat_map`` are
-excluded from this check, because their subscript operator has a defined
-behaviour when a key does not exist (inserting a new element).
+STL containers with well-defined behavior for `operator[] are excluded from this
+check.
 
 This check enforces part of the `SL.con.3
 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>`

>From 02e23973ff6b9e17ab3ab199d806fe6f85236175 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 26 Oct 2024 21:21:47 +0200
Subject: [PATCH 48/54] s/bound-safe/bounds-safe

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 ...oBoundsAvoidUncheckedContainerAccesses.cpp | 10 ++---
 ...nds-avoid-unchecked-container-accesses.cpp | 42 +++++++++----------
 2 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 09950ca516f585..e2f1072bfbaf0d 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -127,7 +127,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
 
   if (SubscriptFixMode == None) {
     diag(MatchedExpr->getCallee()->getBeginLoc(),
-         "possibly unsafe 'operator[]', consider bound-safe alternatives")
+         "possibly unsafe 'operator[]', consider bounds-safe alternatives")
         << MatchedExpr->getCallee()->getSourceRange();
     return;
   }
@@ -148,14 +148,14 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
       if (!Alternative) {
         diag(MatchedExpr->getCallee()->getBeginLoc(),
              "possibly unsafe 'operator[]', consider "
-             "bound-safe alternatives")
+             "bounds-safe alternatives")
             << MatchedExpr->getCallee()->getSourceRange();
         return;
       }
 
       diag(MatchedExpr->getCallee()->getBeginLoc(),
            "possibly unsafe 'operator[]', consider "
-           "bound-safe alternative 'at()'")
+           "bounds-safe alternative 'at()'")
           << MatchedExpr->getCallee()->getSourceRange()
           << FixItHint::CreateReplacement(LeftBracket, ".at(")
           << FixItHint::CreateReplacement(RightBracket, ")");
@@ -192,13 +192,13 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
       const CXXMethodDecl *Alternative = findAlternativeAt(MatchedOperator);
       if (!Alternative) {
         diag(Callee->getBeginLoc(), "possibly unsafe 'operator[]', consider "
-                                    "bound-safe alternative 'at()'")
+                                    "bounds-safe alternative 'at()'")
             << Callee->getSourceRange();
         return;
       }
       diag(MatchedExpr->getCallee()->getBeginLoc(),
            "possibly unsafe 'operator[]', consider "
-           "bound-safe alternative 'at()'")
+           "bounds-safe alternative 'at()'")
           << FixItHint::CreateReplacement(
                  SourceRange(Callee->getMemberLoc(), Callee->getEndLoc()),
                  "at");
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
index b7f5e9ba3e5cb8..9cff7c3e54bf3a 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp
@@ -92,51 +92,51 @@ template<class T> int f(T){ return 0;}
 std::array<int, 3> a;
 
 auto b = a[0];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto b = a.at(0);
 // CHECK-FIXES-FUNC: auto b = f(a, 0);
 
 auto b23 = a[];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto b23 = a.at();
 // CHECK-FIXES-FUNC: auto b23 = f(a);
 
 
 auto c = a[1+1];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto c = a.at(1+1);
 // CHECK-FIXES-FUNC: auto c = f(a, 1+1);
 
 constexpr int Index = 1;
 auto d = a[Index];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto d = a.at(Index);
 // CHECK-FIXES-FUNC: auto d = f(a, Index);
 
 int e(int Ind) {
   return a[Ind];
-  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
   // CHECK-FIXES-AT: return a.at(Ind);
   // CHECK-FIXES-FUNC: return f(a, Ind);
 }
 
 auto fa = (&a)->operator[](1);
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto fa = (&a)->at(1);
 // CHECK-FIXES-FUNC: auto fa = f(*(&a), 1);
 
 auto fd = a.operator[](1);
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto fd = a.at(1);
 // CHECK-FIXES-FUNC: auto fd = f(a, 1);
 //
 auto fa23 = (&a)->operator[]();
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto fa23 = (&a)->at();
 // CHECK-FIXES-FUNC: auto fa23 = f(*(&a));
 
 auto fd23 = a.operator[]();
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto fd23 = a.at();
 // CHECK-FIXES-FUNC: auto fd23 = f(a);
 
@@ -144,38 +144,38 @@ auto g = a.at(0);
 
 std::unique_ptr<int> p;
 auto q = p[0];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto q = p[0];
 // CHECK-FIXES-FUNC: auto q = f(p, 0);
 
 std::span<int> s;
 auto t = s[0];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto t = s[0];
 // CHECK-FIXES-FUNC: auto t = f(s, 0);
 
 json::node<int> n;
 auto m = n[0];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto m = n[0];
 // CHECK-FIXES-FUNC: auto m = f(n, 0);
 
 SubClass Sub;
 auto r = Sub[0];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto r = Sub.at(0);
 // CHECK-FIXES-FUNC: auto r = f(Sub, 0);
 
 typedef std::array<int, 3> ar;
 ar BehindDef;
 auto u = BehindDef[0];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:19: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:19: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto u = BehindDef.at(0);
 // CHECK-FIXES-FUNC: auto u = f(BehindDef, 0);
 
 template<typename T> int TestTemplate(T t){
   return t[0];
-  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:10: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:10: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 }
 
@@ -198,15 +198,15 @@ auto y = TestMap[0];
 #define OBJECT_BEHIND_MACRO a
 
 auto m1 = SUBSCRIPT_BEHIND_MACRO(0);
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 
 auto m2 = a[ARG_BEHIND_MACRO];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto m2 = a.at(ARG_BEHIND_MACRO);
 // CHECK-FIXES-FUNC: auto m2 = f(a, ARG_BEHIND_MACRO);
 
 auto m3 = OBJECT_BEHIND_MACRO[0];
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:30: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:30: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto m3 = OBJECT_BEHIND_MACRO.at(0);
 // CHECK-FIXES-FUNC: auto m3 = f(OBJECT_BEHIND_MACRO, 0);
 
@@ -214,14 +214,14 @@ auto m3 = OBJECT_BEHIND_MACRO[0];
 std::array<int , 3> longname;
 
 auto z1 = longname   [    0    ]  ;
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:22: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:22: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto z1 = longname   .at(    0    )  ;
 // CHECK-FIXES-FUNC: auto z1 = f(longname   ,     0    )  ;
 auto z2 = longname   . operator[]   ( 0 );
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto z2 = longname   . at   ( 0 );
 // CHECK-FIXES-FUNC: auto z2 = f(longname   ,  0 );
 auto z3 = (&longname)   -> operator[]   ( 0 );
-// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bound-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
 // CHECK-FIXES-AT: auto z3 = (&longname)   -> at   ( 0 );
 // CHECK-FIXES-FUNC: auto z3 = f(*(&longname)   ,  0 );

>From 572648b2c4a95bdd9e7d218b49180578cdd395ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 4 Nov 2024 11:13:02 +0100
Subject: [PATCH 49/54] docs: remove whitespace

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 .../pro-bounds-avoid-unchecked-container-accesses.rst           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index b677e1d34e4145..2fb34c795511c4 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -42,7 +42,7 @@ Options
 .. option:: SubscriptFixMode
 
     Determines what fixes are suggested. Either `None` (default), `at` (use 
-    ``a.at(index)`` if a fitting function exists ) or `function` (use a 
+    ``a.at(index)`` if a fitting function exists) or `function` (use a 
     function ``f(a, index)``).
 
 .. option:: SubscriptFixFunction

>From 6ba98f4c73a0cca327d305f95db1fa499e6297bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Tue, 5 Nov 2024 10:33:45 +0100
Subject: [PATCH 50/54] Update clang-tools-extra/docs/ReleaseNotes.rst

Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
 clang-tools-extra/docs/ReleaseNotes.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 36f5999b7d610d..e537e60ac7a62b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -117,7 +117,7 @@ New checks
   <clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>`
   check.
 
-  Flags calls to operator[] in STL containers and suggests replacing it with
+  Flags calls to ``operator[]`` in STL containers and suggests replacing it with
   safe alternatives.
 
 New check aliases

>From 85be05381329859004e9c4cd7e1699508c2c9652 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Tue, 5 Nov 2024 10:34:34 +0100
Subject: [PATCH 51/54] Update
 clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst

Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
 .../pro-bounds-avoid-unchecked-container-accesses.rst           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index 2fb34c795511c4..86bdaf3bdcd9eb 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -22,7 +22,7 @@ will generate a warning but
 
 will generate a warning.
 
-STL containers with well-defined behavior for `operator[] are excluded from this
+STL containers with well-defined behavior for ``operator[]`` are excluded from this
 check.
 
 This check enforces part of the `SL.con.3

>From 67bc281b2fee7594c36e626c794e0fde22c68572 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Tue, 5 Nov 2024 10:34:53 +0100
Subject: [PATCH 52/54] Update
 clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst

Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
 .../pro-bounds-avoid-unchecked-container-accesses.rst           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index 86bdaf3bdcd9eb..e03018f04eeb73 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -3,7 +3,7 @@
 cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
 ===============================================================
 
-Flags calls to operator[] in STL containers and suggests replacing it with
+Flags calls to ``operator[]`` in STL containers and suggests replacing it with
 safe alternatives.
 
 For example the code

>From b05faeed0bb0edf525464f4fc8e816870827de75 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Tue, 5 Nov 2024 10:41:43 +0100
Subject: [PATCH 53/54] Update
 clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst

Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
 .../pro-bounds-avoid-unchecked-container-accesses.rst           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
index e03018f04eeb73..91f6f661def536 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
@@ -37,7 +37,7 @@ Options
 .. option:: SubscriptExcludeClasses
 
     Semicolon-delimited list of class names that should additionally be
-    excluded from this check. By default empty.
+    excluded from this check. The default is an empty string.
 
 .. option:: SubscriptFixMode
 

>From 2d50c5321f279238a91f781e3f49f46a333f8e4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Tue, 5 Nov 2024 11:17:58 +0100
Subject: [PATCH 54/54] docs: fix rebase artifacts in ReleaseNotes.rst

Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
 clang-tools-extra/docs/ReleaseNotes.rst | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index e537e60ac7a62b..8c4b964ab83c19 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -113,13 +113,36 @@ Improvements to clang-tidy
 New checks
 ^^^^^^^^^^
 
+- New :doc:`bugprone-bitwise-pointer-cast
+  <clang-tidy/checks/bugprone/bitwise-pointer-cast>` check.
+
+  Warns about code that tries to cast between pointers by means of
+  ``std::bit_cast`` or ``memcpy``.
+
+- New :doc:`bugprone-nondeterministic-pointer-iteration-order
+  <clang-tidy/checks/bugprone/nondeterministic-pointer-iteration-order>`
+  check.
+
+  Finds nondeterministic usages of pointers in unordered containers.
+
+- New :doc:`bugprone-tagged-union-member-count
+  <clang-tidy/checks/bugprone/tagged-union-member-count>` check.
+
+  Gives warnings for tagged unions, where the number of tags is
+  different from the number of data members inside the union.
+
 - New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
   <clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses>`
-  check.
 
   Flags calls to ``operator[]`` in STL containers and suggests replacing it with
   safe alternatives.
 
+- New :doc:`portability-template-virtual-member-function
+  <clang-tidy/checks/portability/template-virtual-member-function>` check.
+
+  Finds cases when an uninstantiated virtual member function in a template class 
+  causes cross-compiler incompatibility.
+
 New check aliases
 ^^^^^^^^^^^^^^^^^
 



More information about the cfe-commits mailing list