[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 May 27 07:55:25 PDT 2025
https://github.com/paulhdk updated https://github.com/llvm/llvm-project/pull/95220
>From 275f00ce382940feb76b2e60d56cb27308e63a12 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/67] 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 0000000000000..524c21b5bdb81
--- /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 0000000000000..f915729cd7bbe
--- /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 b023f76a25432..991961e0babf4 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 6adef04264347..fc5141aa79451 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -20,6 +20,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 d6f2d2b37624e..0b7748957a11e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -136,6 +136,11 @@ New checks
Finds unintended character output from ``unsigned char`` and ``signed char``
to an ``ostream``.
+- New :doc:`cppcoreguidelines-avoid-bounds-errors
+ <clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors>` check.
+
+ Flags the unsafe `operator[]` and replaces it with `at()`.
+
- New :doc:`portability-avoid-pragma-once
<clang-tidy/checks/portability/avoid-pragma-once>` check.
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 0000000000000..8fb2e3bfde098
--- /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 5a79d61b1fd7e..35285df5ee2ec 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -184,6 +184,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 0000000000000..23453b1f2df21
--- /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 10cc6974327723a83c679f0892ae2e01e2de5225 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/67] EugeneZelenko's comments
---
.../cppcoreguidelines/AvoidBoundsErrorsCheck.cpp | 10 +++++-----
.../cppcoreguidelines/AvoidBoundsErrorsCheck.h | 3 +++
.../checks/cppcoreguidelines/avoid-bounds-errors.rst | 7 ++++---
3 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
index 524c21b5bdb81..2c0a12e21d726 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 f915729cd7bbe..12c7852877123 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/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
index 8fb2e3bfde098..13683ee9b5a46 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 709b70b6477669833da5d9965fbb67468fa59f20 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/67] 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 2c0a12e21d726..f10b97820f4c7 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 23453b1f2df21..5e12e7d71790d 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 dee8d54be9f7334caf699a7cba0a17b7b83eb9f5 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/67] Rename AvoidBoundsErrorsCheck to
PreferAtOverSubscriptOperatorCheck
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
.../clang-tidy/cppcoreguidelines/CMakeLists.txt | 2 +-
.../CppCoreGuidelinesTidyModule.cpp | 6 +++---
...pp => PreferAtOverSubscriptOperatorCheck.cpp} | 9 +++++----
...ck.h => PreferAtOverSubscriptOperatorCheck.h} | 16 ++++++++--------
...rst => prefer-at-over-subscript-operator.rst} | 4 ++--
.../docs/clang-tidy/checks/list.rst | 2 +-
...cpp => prefer-at-over-subscript-operator.cpp} | 12 ++++++------
7 files changed, 26 insertions(+), 25 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 991961e0babf4..c08d09951347e 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
@@ -20,6 +19,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 fc5141aa79451..f42049e853940 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -20,7 +20,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 f10b97820f4c7..64eaf8a1d4ebd 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 12c7852877123..eb6e3a021e1b6 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/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 13683ee9b5a46..183175b596668 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 35285df5ee2ec..272d744a8b578 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -184,7 +184,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>`,
@@ -199,6 +198,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 5e12e7d71790d..45071f8f9f207 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 18f6a5564219ef8a063ff8de6660a3512bdc67d7 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/67] 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 64eaf8a1d4ebd..d7cdbc59d3941 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 eb6e3a021e1b6..f2450a7ab3470 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 45071f8f9f207..7da6c31556969 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 47502cf6eed78f0b9055b80565ff62b5919b7d35 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/67] 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 183175b596668..42a2100f32582 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 988ec162738be445f98ca6730a35bedd978864dd 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/67] 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 7da6c31556969..cc7088bffeda9 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 bfa53fbfabc96746b27bb9946722403f944c08ec 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/67] 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 d7cdbc59d3941..dc036e23e2af1 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 a7e4b261fa803d66d1222a0ad28b7d8c15ef4011 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/67] 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 dc036e23e2af1..0924fda164b4a 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 9c4b46c189401d54dc70f0f508650598512ae193 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/67] 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 42a2100f32582..96c71931ff2a3 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 803da26c92cfea03bda81fb802a9e3506e8eb5b7 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/67] 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 96c71931ff2a3..873564d12dd6b 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 14518585ba2ba9672eb5490093e03c12c65a27dc 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/67] 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 873564d12dd6b..7999cd4baeb7c 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 e1a308440870ca5212703f8c5759f5ee7357f1d9 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/67] 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 cc7088bffeda9..76b84bf860cb6 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 48ab07c5684eba4e58bf7b8401643a037f1ce051 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/67] 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 7999cd4baeb7c..f3577cb5b15f0 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 aa1e472abf62e4cf74cdfe49949ea00f78858120 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/67] 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 0924fda164b4a..d047c0b2332d1 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 17dc5222ef45e9f54c8c689c0bc8555f32420619 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/67] 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 d047c0b2332d1..82a957241042a 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 76b84bf860cb6..4ae17688cb9e2 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 b3f7b8206a8c2d18a36d4433be23391f585fe22f 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/67] 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 82a957241042a..5a5704deae14f 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 ab4248f94407e762be7200b3254e55a6f05be17f 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/67] PreferAtOverSubscriptOpterator ->
ProBoundsAvoidUncheckedContainerAccesses
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
.../cppcoreguidelines/CMakeLists.txt | 2 +-
.../CppCoreGuidelinesTidyModule.cpp | 6 ++---
...BoundsAvoidUncheckedContainerAccesses.cpp} | 16 +++++++-----
...roBoundsAvoidUncheckedContainerAccesses.h} | 15 ++++++-----
...ds-avoid-unchecked-container-accesses.rst} | 4 +--
.../docs/clang-tidy/checks/list.rst | 2 +-
...ds-avoid-unchecked-container-accesses.cpp} | 26 +++++++++----------
7 files changed, 37 insertions(+), 34 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 c08d09951347e..7ee0837f006cc 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -19,9 +19,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 f42049e853940..23823cbc0387a 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 5a5704deae14f..19a52d0e565fa 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 f2450a7ab3470..33abbef5e8243 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/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 f3577cb5b15f0..616882738653d 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 272d744a8b578..81316e335a84f 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -198,9 +198,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 4ae17688cb9e2..1a7a7fba7d8a2 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 784e6442cf7e7010c903276c93f9a014cadcf202 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/67] 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 33abbef5e8243..8fdfd5e9eb518 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 f16539a9d0409990cc144fb461f4aa0ab9f3b5d3 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/67] 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 616882738653d..f39c5171110a0 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 b7cfeeb3278c068b7c474b65d6a2d7d3442a87c4 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/67] 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 f39c5171110a0..b62ec4fc7b6b5 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 1840bbb0cbe6d2fde2cd09e4db88c9178fd81524 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/67] 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 19a52d0e565fa..b68583a77ac7f 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 8fdfd5e9eb518..3776869e6d42a 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 321209e30edd163ff84aa87f8947042bfaba08a5 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/67] 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 b68583a77ac7f..560ccf3c7ca86 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 91f4f151cf946c413bbcb019550e91c69da4750e 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/67] 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 560ccf3c7ca86..054aa852ca664 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 e2f925dfef5fff7bdfaf5eefec42d15fd3ca7d6f 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/67] 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 054aa852ca664..d48b19bb36711 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 c2670fefd47648da7968cab5366982b5c8bf660e 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/67] 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 d48b19bb36711..8998cbfc1aeb2 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 1a7a7fba7d8a2..9801dbb94ae27 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 65a30556088db73105aa203f6a7fea6c236ad336 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/67] 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 8998cbfc1aeb2..324a36296aa77 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 44ce128b865b82a821905731d6faea7e80585bd1 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/67] 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 324a36296aa77..f3dff0769e994 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 4c095bf4666b38e7c87a2921d92f6b1f23a22193 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/67] 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 3776869e6d42a..a4770384db0ab 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 e19f5e91888ecefeb2f8460f0f9228791ba07c32 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/67] 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 b62ec4fc7b6b5..a2ba12100cbf7 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 4bf28a172b06d2f4e043ca25cd5fff1640253feb 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/67] 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 a2ba12100cbf7..1221c38f23883 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 5e99205169d45ed2bf413d6c4e3a7bc3df88ece2 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/67] 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 1221c38f23883..4bc91adb2ee62 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 4f78f32659eb1d65393b7ecf7a371e82f9551d2d 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/67] 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 f3dff0769e994..81cb943082a68 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 adabf582f0bc797161aa15c603136ca4618446d8 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/67] 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 a583cc78b2c54..6034b1542108e 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 64758f4038776f1f0ac18d9245acbe49112a7d8a 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/67] 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 6034b1542108e..a583cc78b2c54 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 aeb0539a853e5164de3d8a1c0c22d3c685a1f86a 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/67] 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 9801dbb94ae27..447b4d1bed195 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 f97b9095aeebc0957e731ec33e3ae317b1119e0f 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/67] 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 81cb943082a68..6435277a020f5 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 9903c6acc3de3649c0a4160b6d23e82e8d000725 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/67] 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 6435277a020f5..c0f1fbd792375 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 d0fdc7e2fbd1db3e390486ef3476c228bceb9c4f 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/67] 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 c0f1fbd792375..2bd4b2b96506a 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 d5155100d64f71f04e8c762e3434489214c4a9f0 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/67] 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 2bd4b2b96506a..77798ccebdf89 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 c20ffa9ecc680bd39ceb69fbd8f30470434f94c3 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/67] 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 77798ccebdf89..09950ca516f58 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 a4770384db0ab..aa2d3e94d0467 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 1eea9c67dbe91a42580c586e95e44f2ce03ea9c0 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/67] Document customizable fixit suggestions
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
...nds-avoid-unchecked-container-accesses.rst | 21 ++++++++++++++-----
.../docs/clang-tidy/checks/list.rst | 2 +-
2 files changed, 17 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 4bc91adb2ee62..62540f106e4bd 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 81316e335a84f..cf1ff9636e72e 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -200,7 +200,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 c479a958733949e8a8f4d4864ed28bb0f04e1400 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/67] 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 447b4d1bed195..b7f5e9ba3e5cb 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 0f4fb6513a1b4739e9254cf2fe1a998949c44d1b 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 44/67] 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 | 3 ++-
.../pro-bounds-avoid-unchecked-container-accesses.rst | 4 ++--
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index aa2d3e94d0467..6e7f28708773e 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 0b7748957a11e..4c067efda3168 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -139,7 +139,8 @@ 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 calls to operator[] in STL containers and suggests replacing it with
+ safe alternatives.
- New :doc:`portability-avoid-pragma-once
<clang-tidy/checks/portability/avoid-pragma-once>` check.
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 62540f106e4bd..3b546446bb065 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 a4507fae8db266d83e9453da5fd6bacdf48f333b 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 45/67] 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 | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 4c067efda3168..076904f00885b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -136,8 +136,9 @@ New checks
Finds unintended character output from ``unsigned char`` and ``signed char``
to an ``ostream``.
-- New :doc:`cppcoreguidelines-avoid-bounds-errors
- <clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors>` check.
+- 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.
>From 6acef6ededc0367e631b6e4450f2d3c7cb95d6c9 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 46/67] 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 3b546446bb065..b677e1d34e414 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 570166f591d301be2f2c7b811064d94a16a67a52 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 47/67] 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 09950ca516f58..e2f1072bfbaf0 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 b7f5e9ba3e5cb..9cff7c3e54bf3 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 c7571b59c587ab57f1c70fa0b5fc4618d418deed 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 48/67] 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 b677e1d34e414..2fb34c795511c 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 647023d8a68e3ffe7fc807e923cb504a257cba02 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 49/67] 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 076904f00885b..39bcdaa5bfc96 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -140,7 +140,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 :doc:`portability-avoid-pragma-once
>From 9d1231556c30ca56150a282b660670c7e61b567b 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 50/67] 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 2fb34c795511c..86bdaf3bdcd9e 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 c2c754402c951cbe21e5a50733a35d233b1c7138 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 51/67] 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 86bdaf3bdcd9e..e03018f04eeb7 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 cd5f763bdc043b72337f6d350e56ff3e36cdd5d8 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 52/67] 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 e03018f04eeb7..91f6f661def53 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 9c21708f876da698ce822d8d212abd1fa08ab9e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Fri, 14 Feb 2025 11:37:13 +0100
Subject: [PATCH 53/67] SubscriptExcludeClasses -> ExcludeClasses
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
.../ProBoundsAvoidUncheckedContainerAccesses.cpp | 2 +-
.../pro-bounds-avoid-unchecked-container-accesses.rst | 2 +-
2 files 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 e2f1072bfbaf0..1902846d675e4 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -55,7 +55,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
std::string Serialized = clang::tidy::utils::options::serializeStringList(
SubscriptExcludedClasses);
- Options.store(Opts, "SubscriptExcludeClasses",
+ Options.store(Opts, "ExcludeClasses",
Serialized.substr(0, Serialized.size() - DefaultsStringLength));
}
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 91f6f661def53..7ea6dd04e742e 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
@@ -34,7 +34,7 @@ profile from the C++ Core Guidelines.
Options
-------
-.. option:: SubscriptExcludeClasses
+.. option:: ExcludeClasses
Semicolon-delimited list of class names that should additionally be
excluded from this check. The default is an empty string.
>From fd5df196586de1499edad360160cf272f603038f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 15 Feb 2025 13:00:08 +0100
Subject: [PATCH 54/67] SubscriptFixMode -> FixMode
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
...oBoundsAvoidUncheckedContainerAccesses.cpp | 20 +++++++++----------
...ProBoundsAvoidUncheckedContainerAccesses.h | 14 ++++++-------
...nds-avoid-unchecked-container-accesses.rst | 2 +-
...nds-avoid-unchecked-container-accesses.cpp | 4 ++--
4 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 1902846d675e4..8c9c9bfb58c7c 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -31,7 +31,7 @@ ProBoundsAvoidUncheckedContainerAccesses::
SubscriptExcludedClasses.insert(SubscriptExcludedClasses.end(),
SubscriptDefaultExclusions.begin(),
SubscriptDefaultExclusions.end());
- SubscriptFixMode = Options.get("SubscriptFixMode", None);
+ FixMode = Options.get("FixMode", None);
SubscriptFixFunction = Options.get("SubscriptFixFunction", "gsl::at");
}
@@ -39,7 +39,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "SubscriptFixFunction", SubscriptFixFunction);
- Options.store(Opts, "SubscriptFixMode", SubscriptFixMode);
+ Options.store(Opts, "FixMode", FixMode);
if (SubscriptExcludedClasses.size() == SubscriptDefaultExclusions.size()) {
Options.store(Opts, "ExcludeClasses", "");
return;
@@ -125,7 +125,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller");
- if (SubscriptFixMode == None) {
+ if (FixMode == None) {
diag(MatchedExpr->getCallee()->getBeginLoc(),
"possibly unsafe 'operator[]', consider bounds-safe alternatives")
<< MatchedExpr->getCallee()->getSourceRange();
@@ -139,7 +139,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
auto RightBracket =
SourceRange(OCE->getOperatorLoc(), OCE->getOperatorLoc());
- if (SubscriptFixMode == At) {
+ if (FixMode == At) {
// Case: a[i] => a.at(i)
const auto *MatchedOperator =
Result.Nodes.getNodeAs<CXXMethodDecl>("operator");
@@ -164,7 +164,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
DiagnosticIDs::Note)
<< Alternative->getNameInfo().getSourceRange();
- } else if (SubscriptFixMode == Function) {
+ } else if (FixMode == Function) {
// Case: a[i] => f(a, i)
diag(MatchedExpr->getCallee()->getBeginLoc(),
"possibly unsafe 'operator[]', use safe function '" +
@@ -183,7 +183,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
// Case: a.operator[](i) or a->operator[](i)
const auto *Callee = dyn_cast<MemberExpr>(MCE->getCallee());
- if (SubscriptFixMode == At) {
+ if (FixMode == At) {
// Cases: a.operator[](i) => a.at(i) and a->operator[](i) => a->at(i)
const auto *MatchedOperator =
@@ -207,7 +207,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
DiagnosticIDs::Note)
<< Alternative->getNameInfo().getSourceRange();
- } else if (SubscriptFixMode == Function) {
+ } else if (FixMode == 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() + "(";
@@ -241,9 +241,9 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
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[] = {
+llvm::ArrayRef<std::pair<P::FixModes, StringRef>>
+OptionEnumMapping<P::FixModes>::getEnumMapping() {
+ static constexpr std::pair<P::FixModes, StringRef> Mapping[] = {
{P::None, "None"}, {P::At, "at"}, {P::Function, "function"}};
return {Mapping};
}
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index 6e7f28708773e..231be970e0480 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -31,13 +31,13 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck {
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
- enum SubscriptFixModes { None, At, Function };
+ enum FixModes { 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;
+ FixModes FixMode;
llvm::StringRef SubscriptFixFunction;
};
} // namespace clang::tidy::cppcoreguidelines
@@ -45,12 +45,10 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck {
namespace clang::tidy {
template <>
struct OptionEnumMapping<
- cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses::
- SubscriptFixModes> {
- static ArrayRef<
- std::pair<cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses::
- SubscriptFixModes,
- StringRef>>
+ cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses::FixModes> {
+ static ArrayRef<std::pair<
+ cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses::FixModes,
+ StringRef>>
getEnumMapping();
};
} // namespace clang::tidy
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 7ea6dd04e742e..04f01b145ba7b 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
@@ -39,7 +39,7 @@ Options
Semicolon-delimited list of class names that should additionally be
excluded from this check. The default is an empty string.
-.. option:: SubscriptFixMode
+.. option:: FixMode
Determines what fixes are suggested. Either `None` (default), `at` (use
``a.at(index)`` if a fitting function exists) or `function` (use a
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 9cff7c3e54bf3..3fac6ca1c43b8 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
@@ -5,12 +5,12 @@
// 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: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: 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.FixMode: function, \
// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.SubscriptFixFunction: "f"}}'
namespace std {
>From fedd5c6e33be9719416998043767cdb4fb2ea94f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 15 Feb 2025 13:03:38 +0100
Subject: [PATCH 55/67] SubscriptFixFunction -> FixFunction
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
.../ProBoundsAvoidUncheckedContainerAccesses.cpp | 12 ++++++------
.../ProBoundsAvoidUncheckedContainerAccesses.h | 2 +-
...pro-bounds-avoid-unchecked-container-accesses.rst | 2 +-
...pro-bounds-avoid-unchecked-container-accesses.cpp | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 8c9c9bfb58c7c..2cc7beb93c7ef 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -32,13 +32,13 @@ ProBoundsAvoidUncheckedContainerAccesses::
SubscriptDefaultExclusions.begin(),
SubscriptDefaultExclusions.end());
FixMode = Options.get("FixMode", None);
- SubscriptFixFunction = Options.get("SubscriptFixFunction", "gsl::at");
+ FixFunction = Options.get("FixFunction", "gsl::at");
}
void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
- Options.store(Opts, "SubscriptFixFunction", SubscriptFixFunction);
+ Options.store(Opts, "FixFunction", FixFunction);
Options.store(Opts, "FixMode", FixMode);
if (SubscriptExcludedClasses.size() == SubscriptDefaultExclusions.size()) {
Options.store(Opts, "ExcludeClasses", "");
@@ -168,10 +168,10 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
// Case: a[i] => f(a, i)
diag(MatchedExpr->getCallee()->getBeginLoc(),
"possibly unsafe 'operator[]', use safe function '" +
- SubscriptFixFunction.str() + "()' instead")
+ FixFunction.str() + "()' instead")
<< MatchedExpr->getCallee()->getSourceRange()
<< FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(),
- SubscriptFixFunction.str() + "(")
+ FixFunction.str() + "(")
// Since C++23, the subscript operator may also be called without an
// argument, which makes the following distinction necessary
<< (MatchedExpr->getDirectCallee()->getNumParams() > 0
@@ -210,14 +210,14 @@ void ProBoundsAvoidUncheckedContainerAccesses::check(
} else if (FixMode == 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() + "(";
+ std::string BeginInsertion = FixFunction.str() + "(";
if (Callee->isArrow())
BeginInsertion += "*";
diag(Callee->getBeginLoc(),
"possibly unsafe 'operator[]', use safe function '" +
- SubscriptFixFunction.str() + "()' instead")
+ FixFunction.str() + "()' instead")
<< Callee->getSourceRange()
<< FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(),
BeginInsertion)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index 231be970e0480..66b2f78495121 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -38,7 +38,7 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck {
std::vector<llvm::StringRef> SubscriptExcludedClasses;
// Setting which fix to suggest
FixModes FixMode;
- llvm::StringRef SubscriptFixFunction;
+ llvm::StringRef FixFunction;
};
} // namespace clang::tidy::cppcoreguidelines
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 04f01b145ba7b..d06bbb0825224 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
@@ -45,6 +45,6 @@ Options
``a.at(index)`` if a fitting function exists) or `function` (use a
function ``f(a, index)``).
-.. option:: SubscriptFixFunction
+.. option:: FixFunction
The function to use in the `function` mode. ``gsl::at`` by default.
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 3fac6ca1c43b8..4ea8c544c12c8 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
@@ -11,7 +11,7 @@
// 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.FixMode: function, \
-// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.SubscriptFixFunction: "f"}}'
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f"}}'
namespace std {
template<typename T, unsigned size>
>From 719f45a28d2576fdd4f4cfcef251c9205c49fe2f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 15 Feb 2025 13:05:54 +0100
Subject: [PATCH 56/67] Remove "Subscript" prefix for variable names
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
...oBoundsAvoidUncheckedContainerAccesses.cpp | 25 +++++++++----------
...ProBoundsAvoidUncheckedContainerAccesses.h | 2 +-
2 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 2cc7beb93c7ef..b6093078019bc 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> SubscriptDefaultExclusions = {
+static constexpr std::array<llvm::StringRef, 3> DefaultExclusions = {
llvm::StringRef("::std::map"), llvm::StringRef("::std::unordered_map"),
llvm::StringRef("::std::flat_map")};
@@ -26,11 +26,10 @@ ProBoundsAvoidUncheckedContainerAccesses::
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
- SubscriptExcludedClasses = clang::tidy::utils::options::parseStringList(
+ ExcludedClasses = clang::tidy::utils::options::parseStringList(
Options.get("ExcludeClasses", ""));
- SubscriptExcludedClasses.insert(SubscriptExcludedClasses.end(),
- SubscriptDefaultExclusions.begin(),
- SubscriptDefaultExclusions.end());
+ ExcludedClasses.insert(ExcludedClasses.end(), DefaultExclusions.begin(),
+ DefaultExclusions.end());
FixMode = Options.get("FixMode", None);
FixFunction = Options.get("FixFunction", "gsl::at");
}
@@ -40,20 +39,20 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
Options.store(Opts, "FixFunction", FixFunction);
Options.store(Opts, "FixMode", FixMode);
- if (SubscriptExcludedClasses.size() == SubscriptDefaultExclusions.size()) {
+ 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(
- SubscriptDefaultExclusions.begin(), SubscriptDefaultExclusions.end(),
- SubscriptDefaultExclusions.size(), std::plus<>(),
- [](llvm::StringRef Name) { return Name.size(); });
+ 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(
- SubscriptExcludedClasses);
+ std::string Serialized =
+ clang::tidy::utils::options::serializeStringList(ExcludedClasses);
Options.store(Opts, "ExcludeClasses",
Serialized.substr(0, Serialized.size() - DefaultsStringLength));
@@ -114,7 +113,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(
mapAnyOf(cxxOperatorCallExpr, cxxMemberCallExpr)
.with(callee(cxxMethodDecl(hasOverloadedOperatorName("[]"),
unless(matchers::matchesAnyListedName(
- SubscriptExcludedClasses)))
+ ExcludedClasses)))
.bind("operator")))
.bind("caller"),
this);
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index 66b2f78495121..f0d4a15cf64fe 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -35,7 +35,7 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck {
private:
// A list of class names that are excluded from the warning
- std::vector<llvm::StringRef> SubscriptExcludedClasses;
+ std::vector<llvm::StringRef> ExcludedClasses;
// Setting which fix to suggest
FixModes FixMode;
llvm::StringRef FixFunction;
>From 1e87e4dd372091abfc8ff952305cf19e6709ae4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 15 Feb 2025 13:06:39 +0100
Subject: [PATCH 57/67] 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 d06bbb0825224..95c4efd410abb 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
@@ -47,4 +47,4 @@ Options
.. option:: FixFunction
- The function to use in the `function` mode. ``gsl::at`` by default.
+ The function to use in the `function` mode. `gsl::at` by default.
>From 1f48531c84347bb418e73f01167510fb6dd16917 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 15 Feb 2025 13:06:56 +0100
Subject: [PATCH 58/67] 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 95c4efd410abb..0f3bed1bbe6bd 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:: ExcludeClasses
Semicolon-delimited list of class names that should additionally be
- excluded from this check. The default is an empty string.
+ excluded from this check. Default is empty string.
.. option:: FixMode
>From add8b5e63c6a2868d006387b5923a977390156c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 15 Feb 2025 13:09:08 +0100
Subject: [PATCH 59/67] Update
clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
closes: https://github.com/llvm/llvm-project/pull/95220#discussion_r1956343401
closes: https://github.com/llvm/llvm-project/pull/95220#discussion_r1956344012
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
.../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 b6093078019bc..60347ee5e439a 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -46,12 +46,12 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
// Sum up the sizes of the defaults ( + semicolons), so we can remove them
// from the saved options
- size_t DefaultsStringLength =
+ const size_t DefaultsStringLength =
std::transform_reduce(DefaultExclusions.begin(), DefaultExclusions.end(),
DefaultExclusions.size(), std::plus<>(),
[](llvm::StringRef Name) { return Name.size(); });
- std::string Serialized =
+ const std::string Serialized =
clang::tidy::utils::options::serializeStringList(ExcludedClasses);
Options.store(Opts, "ExcludeClasses",
>From aee7991776a937da0f8baf915f3ffbe0deebce00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Sat, 15 Feb 2025 13:19:47 +0100
Subject: [PATCH 60/67] Remove contradicting "but" in
cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
.../pro-bounds-avoid-unchecked-container-accesses.rst | 4 ++--
1 file changed, 2 insertions(+), 2 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 0f3bed1bbe6bd..8a87f6b34092d 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
@@ -6,14 +6,14 @@ cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses
Flags calls to ``operator[]`` in STL containers and suggests replacing it with
safe alternatives.
-For example the code
+For example, both
.. code-block:: c++
std::vector<int> a;
int b = a[4];
-will generate a warning but
+and
.. code-block:: c++
>From 2e01617bd8bd841aa873eea8e9d84de4761e33f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 17 Feb 2025 09:22:19 +0100
Subject: [PATCH 61/67] Only match subscript operators with a parameter list of
size 0 or 1
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
.../ProBoundsAvoidUncheckedContainerAccesses.cpp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 60347ee5e439a..0722fc4d56255 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -111,10 +111,12 @@ void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers(
MatchFinder *Finder) {
Finder->addMatcher(
mapAnyOf(cxxOperatorCallExpr, cxxMemberCallExpr)
- .with(callee(cxxMethodDecl(hasOverloadedOperatorName("[]"),
- unless(matchers::matchesAnyListedName(
- ExcludedClasses)))
- .bind("operator")))
+ .with(callee(
+ cxxMethodDecl(
+ hasOverloadedOperatorName("[]"),
+ anyOf(parameterCountIs(0), parameterCountIs(1)),
+ unless(matchers::matchesAnyListedName(ExcludedClasses)))
+ .bind("operator")))
.bind("caller"),
this);
}
>From 278fe273d8c7f569ac3988e1dce73643d4f89cbe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul.heidekrueger at tum.de>
Date: Mon, 17 Feb 2025 10:47:58 +0100
Subject: [PATCH 62/67] Simplify how user-specified excluded classes are stored
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
...roBoundsAvoidUncheckedContainerAccesses.cpp | 18 ++++--------------
.../ProBoundsAvoidUncheckedContainerAccesses.h | 1 +
2 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index 0722fc4d56255..d02737e58945c 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -26,8 +26,9 @@ ProBoundsAvoidUncheckedContainerAccesses::
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
- ExcludedClasses = clang::tidy::utils::options::parseStringList(
- Options.get("ExcludeClasses", ""));
+ ExcludedClassesStr = Options.get("ExcludeClasses", "");
+ ExcludedClasses =
+ clang::tidy::utils::options::parseStringList(ExcludedClassesStr);
ExcludedClasses.insert(ExcludedClasses.end(), DefaultExclusions.begin(),
DefaultExclusions.end());
FixMode = Options.get("FixMode", None);
@@ -44,18 +45,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
return;
}
- // Sum up the sizes of the defaults ( + semicolons), so we can remove them
- // from the saved options
- const size_t DefaultsStringLength =
- std::transform_reduce(DefaultExclusions.begin(), DefaultExclusions.end(),
- DefaultExclusions.size(), std::plus<>(),
- [](llvm::StringRef Name) { return Name.size(); });
-
- const std::string Serialized =
- clang::tidy::utils::options::serializeStringList(ExcludedClasses);
-
- Options.store(Opts, "ExcludeClasses",
- Serialized.substr(0, Serialized.size() - DefaultsStringLength));
+ Options.store(Opts, "ExcludeClasses", ExcludedClassesStr);
}
// TODO: if at() is defined in another class in the class hierarchy of the class
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
index f0d4a15cf64fe..b18f4e14e62b8 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h
@@ -36,6 +36,7 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck {
private:
// A list of class names that are excluded from the warning
std::vector<llvm::StringRef> ExcludedClasses;
+ llvm::StringRef ExcludedClassesStr;
// Setting which fix to suggest
FixModes FixMode;
llvm::StringRef FixFunction;
>From 2a629470092cb29afedcf619898efbb8d7d32e9d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul at paulhdk.com>
Date: Thu, 8 May 2025 12:02:30 +0200
Subject: [PATCH 63/67] Remove unused import
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
.../ProBoundsAvoidUncheckedContainerAccesses.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index d02737e58945c..75227a2a2eeeb 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -11,7 +11,6 @@
#include "../utils/OptionsUtils.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "llvm/ADT/StringRef.h"
-#include <numeric>
using namespace clang::ast_matchers;
>From 5d602e3fd9b1d02d23286d8a012648de4fa65ef0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul at paulhdk.com>
Date: Sat, 10 May 2025 19:00:29 +0200
Subject: [PATCH 64/67] Make FixMode "none" lowercase
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
.../ProBoundsAvoidUncheckedContainerAccesses.cpp | 2 +-
.../pro-bounds-avoid-unchecked-container-accesses.rst | 2 +-
2 files 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 75227a2a2eeeb..b83852af9b953 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -234,7 +234,7 @@ using P = cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses;
llvm::ArrayRef<std::pair<P::FixModes, StringRef>>
OptionEnumMapping<P::FixModes>::getEnumMapping() {
static constexpr std::pair<P::FixModes, StringRef> Mapping[] = {
- {P::None, "None"}, {P::At, "at"}, {P::Function, "function"}};
+ {P::None, "none"}, {P::At, "at"}, {P::Function, "function"}};
return {Mapping};
}
} // namespace clang::tidy
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 8a87f6b34092d..83821c82c8486 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
@@ -41,7 +41,7 @@ Options
.. option:: FixMode
- Determines what fixes are suggested. Either `None` (default), `at` (use
+ 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)``).
>From 2b2215c8c929224ed720694c9791af60c6909996 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul at paulhdk.com>
Date: Sun, 11 May 2025 14:43:51 +0200
Subject: [PATCH 65/67] Separate C++23 tests
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
...nds-avoid-unchecked-container-accesses.cpp | 47 ++++++++++++++-----
1 file changed, 34 insertions(+), 13 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 4ea8c544c12c8..9332833e83c9e 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,27 +1,44 @@
-// RUN: %check_clang_tidy -std=c++2b -check-suffix=DEFAULT %s \
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -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: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -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.FixMode: at}}'
-// RUN: %check_clang_tidy -std=c++2b -check-suffix=FUNC %s \
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -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.FixMode: function, \
// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f"}}'
+// RUN: %check_clang_tidy -std=c++23 -check-suffixes=DEFAULT,DEFAULT-CXX-23 %s \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2"}}' -- -DCXX_23=1
+
+// RUN: %check_clang_tidy -std=c++23 -check-suffixes=AT,AT-CXX-23 %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.FixMode: at}}' -- -DCXX_23=1
+
+// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC,FUNC-CXX-23 %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.FixMode: function, \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f"}}' -- -DCXX_23=1
+
namespace std {
template<typename T, unsigned size>
struct array {
T operator[](unsigned i) {
return T{1};
}
+#ifdef CXX_23
T operator[]() {
return T{1};
}
+#endif
T at(unsigned i) {
return T{1};
}
@@ -96,10 +113,12 @@ auto b = a[0];
// CHECK-FIXES-AT: auto b = a.at(0);
// CHECK-FIXES-FUNC: auto b = f(a, 0);
+#ifdef CXX_23
auto b23 = a[];
-// 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);
+// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-CXX-23: auto b23 = a.at();
+// CHECK-FIXES-FUNC-CXX-23: auto b23 = f(a);
+#endif
auto c = a[1+1];
@@ -129,16 +148,18 @@ auto fd = a.operator[](1);
// 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);
-//
+
+#ifdef CXX_23
auto fa23 = (&a)->operator[]();
-// 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));
+// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-CXX-23: auto fa23 = (&a)->at();
+// CHECK-FIXES-FUNC-CXX-23: auto fa23 = f(*(&a));
auto fd23 = a.operator[]();
-// 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);
+// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-CXX-23: auto fd23 = a.at();
+// CHECK-FIXES-FUNC-CXX-23: auto fd23 = f(a);
+#endif
auto g = a.at(0);
>From fec707280c9b9b22f0900f0ab038a11ece1a8cc9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul at paulhdk.com>
Date: Tue, 27 May 2025 16:15:47 +0200
Subject: [PATCH 66/67] Change semantics around excluded classes
The ExcludedClasses option now overwrites the default exclusions and
does not extend them.
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
.../ProBoundsAvoidUncheckedContainerAccesses.cpp | 14 +++-----------
...o-bounds-avoid-unchecked-container-accesses.rst | 7 ++++---
2 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
index b83852af9b953..0e6fd88ab9218 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp
@@ -16,20 +16,17 @@ 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")};
+static constexpr llvm::StringRef DefaultExclusionStr =
+ "::std::map;::std::unordered_map;::std::flat_map";
ProBoundsAvoidUncheckedContainerAccesses::
ProBoundsAvoidUncheckedContainerAccesses(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
- ExcludedClassesStr = Options.get("ExcludeClasses", "");
+ ExcludedClassesStr = Options.get("ExcludeClasses", DefaultExclusionStr);
ExcludedClasses =
clang::tidy::utils::options::parseStringList(ExcludedClassesStr);
- ExcludedClasses.insert(ExcludedClasses.end(), DefaultExclusions.begin(),
- DefaultExclusions.end());
FixMode = Options.get("FixMode", None);
FixFunction = Options.get("FixFunction", "gsl::at");
}
@@ -39,11 +36,6 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions(
Options.store(Opts, "FixFunction", FixFunction);
Options.store(Opts, "FixMode", FixMode);
- if (ExcludedClasses.size() == DefaultExclusions.size()) {
- Options.store(Opts, "ExcludeClasses", "");
- return;
- }
-
Options.store(Opts, "ExcludeClasses", ExcludedClassesStr);
}
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 83821c82c8486..9832c0706129a 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
@@ -36,9 +36,10 @@ Options
.. option:: ExcludeClasses
- Semicolon-delimited list of class names that should additionally be
- excluded from this check. Default is empty string.
-
+ Semicolon-delimited list of class names for overwriting the default
+ exclusion list. The default is:
+ ``::std::map;::std::unordered_map;::std::flat_map``.
+
.. option:: FixMode
Determines what fixes are suggested. Either `none` (default), `at` (use
>From ab44c0a9ba6c965a899bd89af6eeb0cac23da07d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <paul at paulhdk.com>
Date: Tue, 27 May 2025 16:16:31 +0200
Subject: [PATCH 67/67] Add tests for new "ExcludedClasses" semantics and split
tests into separate fiels with split-file
Co-authored-by: Manuel Pietsch <manuelpietsch at outlook.de>
---
...nds-avoid-unchecked-container-accesses.cpp | 210 ++++++++++++------
1 file changed, 142 insertions(+), 68 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 9332833e83c9e..32b48309122cc 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,32 +1,65 @@
-// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=DEFAULT %s \
+// RUN: rm -rf %t && mkdir %t
+// RUN: split-file %s %t
+
+
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=DEFAULT %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.cpp \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- -- -I%t
+
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=AT %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.cpp \
// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
-// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2"}}'
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: at}}' -- -I%t
-// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=AT %s \
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=FUNC %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.cpp \
// 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.FixMode: at}}'
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: function, \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f"}}' -- -I%t
-// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=FUNC %s \
+
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=DEFAULT-NO-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-no-excl.cpp \
// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
-// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2", \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: ""}}' -- -I%t
+
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=AT-NO-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-no-excl.cpp \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "", \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: at}}' -- -I%t
+
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=FUNC-NO-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-no-excl.cpp \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "", \
// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: function, \
-// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f"}}'
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f"}}' -- -I%t
+
-// RUN: %check_clang_tidy -std=c++23 -check-suffixes=DEFAULT,DEFAULT-CXX-23 %s \
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=DEFAULT-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-excl.cpp \
// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
-// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2"}}' -- -DCXX_23=1
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "ExcludedClass1;ExcludedClass2"}}' -- -I%t
-// RUN: %check_clang_tidy -std=c++23 -check-suffixes=AT,AT-CXX-23 %s \
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=AT-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-excl.cpp \
// 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.FixMode: at}}' -- -DCXX_23=1
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "ExcludedClass1;ExcludedClass2", \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: at}}' -- -I%t
-// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC,FUNC-CXX-23 %s \
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=FUNC-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-excl.cpp \
// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
-// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "::ExcludedClass1;::ExcludedClass2", \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.ExcludeClasses: "ExcludedClass1;ExcludedClass2", \
// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: function, \
-// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f"}}' -- -DCXX_23=1
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f"}}' -- -I%t
+
+
+// RUN: %check_clang_tidy -std=c++23 -check-suffixes=DEFAULT-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-cxx-23.cpp \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- -- -I%t -DCXX_23=1
+
+// RUN: %check_clang_tidy -std=c++23 -check-suffixes=AT-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-cxx-23.cpp \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: at}}' -- -I%t -DCXX_23=1
+
+// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-cxx-23.cpp \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses %t -- \
+// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: function, \
+// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f"}}' -- -I%t -DCXX_23=1
+
+//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h
namespace std {
template<typename T, unsigned size>
@@ -34,11 +67,6 @@ namespace std {
T operator[](unsigned i) {
return T{1};
}
-#ifdef CXX_23
- T operator[]() {
- return T{1};
- }
-#endif
T at(unsigned i) {
return T{1};
}
@@ -81,27 +109,11 @@ namespace json {
};
} // namespace json
-struct SubClass : std::array<int, 3> {};
+//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.cpp
-class ExcludedClass1 {
- public:
- int operator[](unsigned i) {
- return 1;
- }
- int at(unsigned i) {
- return 1;
- }
-};
+#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h"
-class ExcludedClass2 {
- public:
- int operator[](unsigned i) {
- return 1;
- }
- int at(unsigned i) {
- return 1;
- }
-};
+struct SubClass : std::array<int, 3> {};
template<class T> int f(T, unsigned){ return 0;}
template<class T> int f(T){ return 0;}
@@ -113,20 +125,13 @@ auto b = a[0];
// CHECK-FIXES-AT: auto b = a.at(0);
// CHECK-FIXES-FUNC: auto b = f(a, 0);
-#ifdef CXX_23
-auto b23 = a[];
-// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
-// CHECK-FIXES-AT-CXX-23: auto b23 = a.at();
-// CHECK-FIXES-FUNC-CXX-23: auto b23 = f(a);
-#endif
-
-
auto c = a[1+1];
// 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 bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
// CHECK-FIXES-AT: auto d = a.at(Index);
@@ -149,17 +154,7 @@ auto fd = a.operator[](1);
// CHECK-FIXES-AT: auto fd = a.at(1);
// CHECK-FIXES-FUNC: auto fd = f(a, 1);
-#ifdef CXX_23
-auto fa23 = (&a)->operator[]();
-// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
-// CHECK-FIXES-AT-CXX-23: auto fa23 = (&a)->at();
-// CHECK-FIXES-FUNC-CXX-23: auto fa23 = f(*(&a));
-auto fd23 = a.operator[]();
-// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
-// CHECK-FIXES-AT-CXX-23: auto fd23 = a.at();
-// CHECK-FIXES-FUNC-CXX-23: auto fd23 = f(a);
-#endif
auto g = a.at(0);
@@ -204,16 +199,6 @@ template<typename T> int TestTemplate(T t){
auto v = TestTemplate<>(a);
auto w = TestTemplate<>(p);
-//excluded classes
-ExcludedClass1 E1;
-auto x1 = E1[0];
-
-ExcludedClass2 E2;
-auto x2 = E1[0];
-
-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
@@ -246,3 +231,92 @@ auto z3 = (&longname) -> operator[] ( 0 );
// 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 );
+
+
+//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-no-excl.cpp
+
+#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h"
+
+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;
+ }
+};
+
+ExcludedClass1 E1;
+auto x1 = E1[0];
+// CHECK-MESSAGES-DEFAULT-NO-EXCL: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-NO-EXCL: auto x1 = E1.at(0);
+// CHECK-FIXES-FUNC-NO-EXCL: auto x1 = f(E1, 0);
+
+ExcludedClass2 E2;
+auto x2 = E2[0];
+// CHECK-MESSAGES-DEFAULT-NO-EXCL: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-NO-EXCL: auto x2 = E2.at(0);
+// CHECK-FIXES-FUNC-NO-EXCL: auto x2 = f(E2, 0);
+
+std::map<int,int> TestMapNoExcl;
+auto y = TestMapNoExcl[0];
+// CHECK-MESSAGES-DEFAULT-NO-EXCL: :[[@LINE-1]]:23: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-NO-EXCL: auto y = TestMapNoExcl.at(0);
+// CHECK-FIXES-FUNC-NO-EXCL: auto y = f(TestMapNoExcl, 0);
+
+
+//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-excl.cpp
+
+#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h"
+
+std::map<int,int> TestMapExcl;
+auto y = TestMapExcl[0];
+// CHECK-MESSAGES-DEFAULT-EXCL: :[[@LINE-1]]:21: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-EXCL: auto y = TestMapExcl.at(0);
+// CHECK-FIXES-FUNC-EXCL: auto y = f(TestMapExcl, 0);
+
+
+//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-cxx-23.cpp
+#ifdef CXX_23
+#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h"
+
+namespace std {
+ template<typename T, unsigned size>
+ struct array_cxx_23 {
+ T operator[]() {
+ return T{1};
+ }
+ T at() {
+ return T{1};
+ }
+ };
+};
+
+std::array_cxx_23<int, 3> a;
+
+auto b23 = a[];
+// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-CXX-23: auto b23 = a.at();
+// CHECK-FIXES-FUNC-CXX-23: auto b23 = f(a);
+
+auto fa23 = (&a)->operator[]();
+// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-CXX-23: auto fa23 = (&a)->at();
+// CHECK-FIXES-FUNC-CXX-23: auto fa23 = f(*(&a));
+
+auto fd23 = a.operator[]();
+// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses]
+// CHECK-FIXES-AT-CXX-23: auto fd23 = a.at();
+// CHECK-FIXES-FUNC-CXX-23: auto fd23 = f(a);
+#endif
More information about the cfe-commits
mailing list