From 3f57fca6253cc8d89447038b8bad357d3d2201a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 4 Aug 2025 09:48:20 +0200 Subject: [PATCH 001/101] 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 +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("x"); + const auto *MatchedFunction = Result.Nodes.getNodeAs("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 2fb4d7f1d7349..c1455e6e45e7d 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 4b3b7bf963fdc..d97eca8deeeef 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" @@ -58,6 +59,8 @@ namespace cppcoreguidelines { class CppCoreGuidelinesModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "cppcoreguidelines-avoid-bounds-errors"); CheckFactories.registerCheck( "cppcoreguidelines-avoid-capturing-lambda-coroutines"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 85b31bc0b42a6..c84072edee0cd 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -118,6 +118,11 @@ New checks Detects default initialization (to 0) of variables with ``enum`` type where the enum has no enumerator with value of 0. +- New :doc:`cppcoreguidelines-avoid-bounds-errors + ` check. + + Flags the unsafe `operator[]` and replaces it with `at()`. + - New :doc:`llvm-mlir-op-builder ` 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 ` 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 a; + int b = a[4]; + +will be replaced by + +.. code-block:: c++ + std::vector 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 b6444eb3c9aec..22d62f0928e5a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -185,6 +185,7 @@ Clang-Tidy Checks :doc:`cert-oop58-cpp `, :doc:`concurrency-mt-unsafe `, :doc:`concurrency-thread-canceltype-asynchronous `, + :doc:`cppcoreguidelines-avoid-bounds-errors `, "Yes" :doc:`cppcoreguidelines-avoid-capturing-lambda-coroutines `, :doc:`cppcoreguidelines-avoid-const-or-ref-data-members `, :doc:`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 + struct array { + T operator[](unsigned i) { + return T{1}; + } + T at(unsigned i) { + return T{1}; + } + }; + + template + struct unique_ptr { + T operator[](unsigned i) { + return T{1}; + } + }; + + template + struct span { + T operator[](unsigned i) { + return T{1}; + } + }; +} // namespace std + +namespace json { + template + struct node{ + T operator[](unsigned i) { + return T{1}; + } + }; +} // namespace json + + +// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-bounds-errors %t +std::array 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 p; +auto q = p[0]; + +std::span s; +auto t = s[0]; + +json::node n; +auto m = n[0]; From b8bbd2c25fbcc48e7038f8fd12c19b7cae91b479 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Fri, 26 Apr 2024 09:06:02 +0200 Subject: [PATCH 002/101] 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 + 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("x"); - const auto *MatchedFunction = Result.Nodes.getNodeAs("f"); - const auto Type = MatchedFunction->getThisType(); + const CallExpr *MatchedExpr = Result.Nodes.getNodeAs("x"); + const CXXMethodDecl *MatchedFunction = Result.Nodes.getNodeAs("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 ` 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 a; int b = a.at(4); + +This check enforces the `SL.con.3 ` guideline. From 168fc45e6f33bd6d40f10a52a011555445563e15 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Fri, 24 May 2024 12:09:11 +0200 Subject: [PATCH 003/101] 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 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(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("x"); - const CXXMethodDecl *MatchedFunction = Result.Nodes.getNodeAs("f"); - const QualType Type = MatchedFunction->getThisType(); - if (!isApplicable(Type)) { - return; - } + const CallExpr *MatchedExpr = Result.Nodes.getNodeAs("caller"); + const CXXMethodDecl *MatchedOperator = + Result.Nodes.getNodeAs("operator"); + const CXXRecordDecl *MatchedParent = + Result.Nodes.getNodeAs("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 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 p; auto q = p[0]; From 9392bf6654198d8fafee26d19fb7ba1d19d79540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 10 Jun 2024 20:56:39 +0200 Subject: [PATCH 004/101] Rename AvoidBoundsErrorsCheck to PreferAtOverSubscriptOperatorCheck Co-authored-by: Manuel Pietsch --- .../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 c1455e6e45e7d..51b911052dc8a 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 d97eca8deeeef..0e2f53a1405d4 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" @@ -59,8 +59,6 @@ namespace cppcoreguidelines { class CppCoreGuidelinesModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { - CheckFactories.registerCheck( - "cppcoreguidelines-avoid-bounds-errors"); CheckFactories.registerCheck( "cppcoreguidelines-avoid-capturing-lambda-coroutines"); CheckFactories.registerCheck( @@ -106,6 +104,8 @@ class CppCoreGuidelinesModule : public ClangTidyModule { "cppcoreguidelines-non-private-member-variables-in-classes"); CheckFactories.registerCheck( "cppcoreguidelines-owning-memory"); + CheckFactories.registerCheck( + "cppcoreguidelines-prefer-at-over-subscript-operator"); CheckFactories.registerCheck( "cppcoreguidelines-prefer-member-initializer"); CheckFactories.registerCheck( 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(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("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 22d62f0928e5a..3476a7db93c84 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -185,7 +185,6 @@ Clang-Tidy Checks :doc:`cert-oop58-cpp `, :doc:`concurrency-mt-unsafe `, :doc:`concurrency-thread-canceltype-asynchronous `, - :doc:`cppcoreguidelines-avoid-bounds-errors `, "Yes" :doc:`cppcoreguidelines-avoid-capturing-lambda-coroutines `, :doc:`cppcoreguidelines-avoid-const-or-ref-data-members `, :doc:`cppcoreguidelines-avoid-do-while `, @@ -200,6 +199,7 @@ Clang-Tidy Checks :doc:`cppcoreguidelines-no-malloc `, :doc:`cppcoreguidelines-no-suspend-with-lock `, :doc:`cppcoreguidelines-owning-memory `, + :doc:`cppcoreguidelines-prefer-at-over-subscript-operator `, :doc:`cppcoreguidelines-prefer-member-initializer `, "Yes" :doc:`cppcoreguidelines-pro-bounds-array-to-pointer-decay `, :doc:`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 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 68d7481175e05d05da7ebdfed00244e8a87f0d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 10 Jun 2024 22:14:54 +0200 Subject: [PATCH 005/101] Add a user-customizable mechanism for excluding classes from the analysis Co-authored-by: Manuel Pietsch --- .../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 +#include using namespace clang::ast_matchers; namespace clang::tidy::cppcoreguidelines { +static constexpr std::array 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("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 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 a; auto b = a[0]; @@ -63,3 +86,14 @@ auto t = s[0]; json::node n; auto m = n[0]; + +//explicitely excluded classes / struct / template +ExcludedClass1 E1; +auto x1 = E1[0]; + +ExcludedClass2 E2; +auto x2 = E1[0]; + +std::map TestMap; +auto y = TestMap[0]; + From 6e778717a607536ec54dcf5077baa9fb336d0b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 10 Jun 2024 22:16:49 +0200 Subject: [PATCH 006/101] Update the documentation Co-authored-by: Manuel Pietsch --- .../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 a; int b = a[4]; -will be replaced by +will generate a warning but .. code-block:: c++ - std::vector a; - int b = a.at(4); + std::unique_ptr a; + int b = a[0]; -This check enforces the `SL.con.3 ` 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 ` guideline. From 5b90a59a74d2ba8c0accc5e02e9212c3d74dc99b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 10 Jun 2024 21:43:23 +0200 Subject: [PATCH 007/101] Add remaining tests requested by @PiotrZSL Co-authored-by: Manuel Pietsch --- .../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 + struct map { + T operator[](unsigned i) { + return T{1}; + } + T at(unsigned i) { + return T{1}; + } + }; + template struct unique_ptr { T operator[](unsigned i) { @@ -33,6 +43,7 @@ namespace json { }; } // namespace json +struct SubClass : std::array {}; class ExcludedClass1 { public: @@ -62,15 +73,17 @@ std::array 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 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 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 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 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 d1a1e6f3026a08cb1c824b4508e7ed65c5d263cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 10 Jun 2024 22:22:21 +0200 Subject: [PATCH 008/101] Remove unused and rename variables Co-authored-by: Manuel Pietsch --- .../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("caller"); const CXXMethodDecl *MatchedOperator = Result.Nodes.getNodeAs("operator"); From 52dd31ca4447844b293ba71a67f548a7e9eec070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Wed, 12 Jun 2024 16:56:40 +0200 Subject: [PATCH 009/101] Update types in PreferAtOverSubscriptOperatorCheck::check() Co-authored-by: Manuel Pietsch --- .../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("caller"); - const CXXMethodDecl *MatchedOperator = + const auto *MatchedExpr = Result.Nodes.getNodeAs("caller"); + const auto *MatchedOperator = Result.Nodes.getNodeAs("operator"); - const CXXRecordDecl *MatchedParent = - Result.Nodes.getNodeAs("parent"); + const auto *MatchedParent = Result.Nodes.getNodeAs("parent"); std::string ClassIdentifier = MatchedParent->getQualifiedNameAsString(); From 72566731436fde74bd866fb1e46415e666334af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Wed, 12 Jun 2024 17:00:00 +0200 Subject: [PATCH 010/101] Fix length of underline in prefer-at-over-subscript-operator.rst Co-authored-by: Manuel Pietsch --- .../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 1f7391d510f7b1e5bb34d2bca49456ac4457a030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Wed, 12 Jun 2024 17:02:33 +0200 Subject: [PATCH 011/101] Enforce 80 char column width in prefer-at-over-subscript-operator.rst Co-authored-by: Manuel Pietsch --- .../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 ` guideline. +This check enforces part of the `SL.con.3 +` +guideline. From e1d81a44ce1ae6c47ea383d7f2fd2cc1b060f66a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Thu, 13 Jun 2024 10:18:58 +0200 Subject: [PATCH 012/101] Synchronise prefer-at-over-subscript-operator.rst with ReleaseNotes.rst Co-authored-by: Manuel Pietsch --- .../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 0dcff27c6e26533c21be035658c48009a317f1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 17 Jun 2024 12:03:57 +0200 Subject: [PATCH 013/101] Move RUN lines to the top of prefer-at-over-subscript-operator.cpp Co-authored-by: Manuel Pietsch --- .../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 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 a; auto b = a[0]; From 71a3b57ce0003300956d69ccbe626cc4daeaed13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 17 Jun 2024 12:05:10 +0200 Subject: [PATCH 014/101] Add an empty lien after each `code-block` in prefer-at-over-subscript-operator.rst Co-authored-by: Manuel Pietsch --- .../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 a; int b = a[4]; will generate a warning but .. code-block:: c++ + std::unique_ptr a; int b = a[0]; From 7fb8ed604b2cab8d4a6a9e67aebb15b59a3248bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 17 Jun 2024 12:08:56 +0200 Subject: [PATCH 015/101] Use ofClass() instead of hasParent() in PreferAtOverSubscriptOperatorCheck.cpp Co-authored-by: Manuel Pietsch --- .../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 76258666f7fff25b561a4cadeab827f03bc497d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 17 Jun 2024 12:42:33 +0200 Subject: [PATCH 016/101] Use matchesAnyListedName() in matcher instead of explicit std::find() check Co-authored-by: Manuel Pietsch --- .../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 #include using namespace clang::ast_matchers; @@ -18,8 +18,8 @@ using namespace clang::ast_matchers; namespace clang::tidy::cppcoreguidelines { static constexpr std::array 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("operator"); const auto *MatchedParent = Result.Nodes.getNodeAs("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 From 6f0a7c62620c452a274504719d4ccdfa7c8cb175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 17 Jun 2024 14:23:35 +0200 Subject: [PATCH 017/101] Match source range of expression in warnings emitted by PreferAtOverSubscriptOperatorCheck Co-authored-by: Manuel Pietsch --- .../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 a52d03de336204716093b6f3c433469c11f6dea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Fri, 21 Jun 2024 10:42:45 +0200 Subject: [PATCH 018/101] PreferAtOverSubscriptOpterator -> ProBoundsAvoidUncheckedContainerAccesses Co-authored-by: Manuel Pietsch --- .../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 51b911052dc8a..b7da037b8d8bc 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 0e2f53a1405d4..f2a356f9e9ba3 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" @@ -104,12 +104,12 @@ class CppCoreGuidelinesModule : public ClangTidyModule { "cppcoreguidelines-non-private-member-variables-in-classes"); CheckFactories.registerCheck( "cppcoreguidelines-owning-memory"); - CheckFactories.registerCheck( - "cppcoreguidelines-prefer-at-over-subscript-operator"); CheckFactories.registerCheck( "cppcoreguidelines-prefer-member-initializer"); CheckFactories.registerCheck( "cppcoreguidelines-pro-bounds-array-to-pointer-decay"); + CheckFactories.registerCheck( + "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses"); CheckFactories.registerCheck( "cppcoreguidelines-pro-bounds-constant-array-index"); CheckFactories.registerCheck( 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 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(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("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 3476a7db93c84..6c4b37ab2a0a3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -199,9 +199,9 @@ Clang-Tidy Checks :doc:`cppcoreguidelines-no-malloc `, :doc:`cppcoreguidelines-no-suspend-with-lock `, :doc:`cppcoreguidelines-owning-memory `, - :doc:`cppcoreguidelines-prefer-at-over-subscript-operator `, :doc:`cppcoreguidelines-prefer-member-initializer `, "Yes" :doc:`cppcoreguidelines-pro-bounds-array-to-pointer-decay `, + :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses `, :doc:`cppcoreguidelines-pro-bounds-constant-array-index `, "Yes" :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic `, :doc:`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 @@ -72,22 +72,22 @@ class ExcludedClass2 { std::array 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 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 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 e38b2aeb2111f93a77a157f6c4e7198b3c19d692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Fri, 21 Jun 2024 10:44:39 +0200 Subject: [PATCH 019/101] Remove extra comment Co-authored-by: Manuel Pietsch --- .../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 48b75ddd09b0c3396190c018e8e0b9a9f6637c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Fri, 21 Jun 2024 10:52:42 +0200 Subject: [PATCH 020/101] Mention bounds safety profile explicitly Co-authored-by: Manuel Pietsch --- .../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 ` -guideline. +guideline and is part of the `Bounds Safety (Bounds 4) +` profile +profile from the C++ Core Guidelines. From b8be8bf6ee5251c8e9c510faeedd0f9140118de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Fri, 21 Jun 2024 10:55:53 +0200 Subject: [PATCH 021/101] Move paragraph about which rule/profile is being implemented above "Options" Co-authored-by: Manuel Pietsch --- ...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 +` +guideline and is part of the `Bounds Safety (Bounds 4) +` 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 -` -guideline and is part of the `Bounds Safety (Bounds 4) -` profile -profile from the C++ Core Guidelines. From 77eee28e064f1980870d20114f71abe99939be13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Fri, 21 Jun 2024 11:09:05 +0200 Subject: [PATCH 022/101] Rename variables related to class exclusion mechanism Co-authored-by: Manuel Pietsch --- ...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 DefaultExclusions = { +static constexpr std::array 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 ExcludedClasses; + std::vector SubscriptExcludedClasses; }; } // namespace clang::tidy::cppcoreguidelines From 10c606353857f418c389f2e5bf0a430c4f94801f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sun, 30 Jun 2024 14:57:07 +0200 Subject: [PATCH 023/101] Remove redundant nullptr cast Co-authored-by: Manuel Pietsch --- .../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(nullptr); + return nullptr; } void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers( From c1b0a0f6e422db9198cf596993cd2bfd70d493f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sun, 30 Jun 2024 15:04:00 +0200 Subject: [PATCH 024/101] Refactor the check's matcher as per 5chmidti's suggestion Co-authored-by: Manuel Pietsch --- ...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("caller"); const auto *MatchedOperator = Result.Nodes.getNodeAs("operator"); - const auto *MatchedParent = Result.Nodes.getNodeAs("parent"); - const CXXMethodDecl *Alternative = - findAlternative(MatchedParent, MatchedOperator); + const CXXMethodDecl *Alternative = findAlternative(MatchedOperator); if (!Alternative) return; From def978bf7bf79facf17c32d6be51f31a07c6fb6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sun, 30 Jun 2024 15:15:10 +0200 Subject: [PATCH 025/101] Check that alternative is accessible in findAlternative() as per @5chmidti's and @PiotrZSL's suggestions Co-authored-by: Manuel Pietsch --- .../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 eb755e307ff70989a8335f38f1d0512ea68d0c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sun, 30 Jun 2024 15:28:10 +0200 Subject: [PATCH 026/101] Use upticks when diagnostic messages refer to code Co-authored-by: Manuel Pietsch --- ...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 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 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 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 13bd78bd84c3750798bc16600ba4e44ad3741126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sun, 30 Jun 2024 15:31:24 +0200 Subject: [PATCH 027/101] Make findAlternative() static Co-authored-by: Manuel Pietsch --- .../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 a572f223ab1692fb9756f7b97be898071d6c64c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sun, 30 Jun 2024 15:33:49 +0200 Subject: [PATCH 028/101] Move MatchedExpr definition closer to where it's first used in ProBoundsAvoidUncheckedContainerAccesses::check() Co-authored-by: Manuel Pietsch --- .../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("caller"); const auto *MatchedOperator = Result.Nodes.getNodeAs("operator"); - const CXXMethodDecl *Alternative = findAlternative(MatchedOperator); + if (!Alternative) return; + const auto *MatchedExpr = Result.Nodes.getNodeAs("caller"); + diag(MatchedExpr->getBeginLoc(), "found possibly unsafe 'operator[]', consider using 'at()' instead") << MatchedExpr->getSourceRange(); From c1d504dde23fc4a851ee7f7eea8a57d53ba12b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sun, 30 Jun 2024 15:37:57 +0200 Subject: [PATCH 029/101] Synchronise comment in header file with ReleaseNotes and check description Co-authored-by: Manuel Pietsch --- .../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 e21e660bf41ab474701a4a80c612ca0d453f99f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 8 Jul 2024 11:05:49 +0200 Subject: [PATCH 030/101] Reword reasoning re: class exclusion in pro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: Manuel Pietsch --- .../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 ca06e1c49b0fc11e25b85bdc0382eb82877de642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 8 Jul 2024 11:15:32 +0200 Subject: [PATCH 031/101] Replace array with container inpro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: Manuel Pietsch --- .../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 a; + std::vector a; int b = a[4]; will generate a warning but From 287a659ae15951a86fa8aa0ed4c6392c0ce89260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 8 Jul 2024 11:17:39 +0200 Subject: [PATCH 032/101] Update unique_ptr example in pro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: Manuel Pietsch --- .../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 a; + std::unique_ptr a; int b = a[0]; will not. From 939f7928e30a0227a62776ef3a0e87252107cd4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 8 Jul 2024 12:15:00 +0200 Subject: [PATCH 033/101] Remove outdated comment in ProBoundsAvoidUncheckedContainerAccess.cpp Co-authored-by: Manuel Pietsch --- .../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 026c64b890186293b0f17d6d5576d394263c7608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 8 Jul 2024 12:21:27 +0200 Subject: [PATCH 034/101] Use TK_IgnoreUnlessSpelledInSource as traversal kind Co-authored-by: Manuel Pietsch --- .../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 getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; From 86e342ca537ee7b7900f8cf6610e577be0ce3175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Thu, 25 Jul 2024 13:30:42 +0200 Subject: [PATCH 035/101] Revert "Use TK_IgnoreUnlessSpelledInSource as traversal kind" This reverts commit ed2076750349881a2613816746fadd792212bb01. Co-authored-by: Manuel Pietsch --- .../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 getCheckTraversalKind() const override { - return TK_IgnoreUnlessSpelledInSource; - } - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; From a7c14e1c7fd394b784cd08b5376cb4bdce34cb16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Fri, 2 Aug 2024 16:44:02 +0200 Subject: [PATCH 036/101] Add template test with std::map as an argument Co-authored-by: Manuel Pietsch --- .../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 int TestTemplate(T t){ } + auto v = TestTemplate<>(a); auto w = TestTemplate<>(p); +std::map 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 TestMap; -auto y = TestMap[0]; - #define SUBSCRIPT_BEHIND_MARCO(x) a[x] #define ARG_BEHIND_MACRO 0 #define OBJECT_BEHIND_MACRO a From d4ac05d40782292861a81ac18e676be746322623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Fri, 2 Aug 2024 16:53:35 +0200 Subject: [PATCH 037/101] Use getNameInfo().getSourceRange() instead of getSourceRange() when printing the location of the alternative Co-authored-by: Manuel Pietsch --- .../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 1e6c970cac45c5893dde0ef1107685d7c1642055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 3 Aug 2024 22:04:25 +0200 Subject: [PATCH 038/101] Replace use of Method->getNameInfo().getAsString() with Method->getName() Co-authored-by: Manuel Pietsch --- .../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 ee6c0aacc79b1425aefb49f710c1b4c467a9843c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Thu, 8 Aug 2024 11:33:36 +0200 Subject: [PATCH 039/101] Add TODO comment re: findAlternative()'s capabilities in class hierarchies Co-authored-by: Manuel Pietsch --- .../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 feef504b08a229bb2c191f03a892b6a44fd31f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Thu, 8 Aug 2024 12:52:25 +0200 Subject: [PATCH 040/101] Reduce size of SourceRange when printing warnings Co-authored-by: Manuel Pietsch --- .../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("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 867dd4c592fc1f9f17dedb1fc88fc7ce718baef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Thu, 8 Aug 2024 16:09:34 +0200 Subject: [PATCH 041/101] Add customizable fixit suggestions Co-authored-by: Manuel Pietsch --- ...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("operator"); - const CXXMethodDecl *Alternative = findAlternative(MatchedOperator); - - if (!Alternative) - return; const auto *MatchedExpr = Result.Nodes.getNodeAs("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(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("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(MatchedExpr)) { + // Case: a.operator[](i) or a->operator[](i) + const auto *Callee = dyn_cast(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("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(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> +OptionEnumMapping::getEnumMapping() { + static constexpr std::pair 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 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> + getEnumMapping(); +}; +} // namespace clang::tidy #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_AVOID_UNCHECKED_CONTAINER_ACCESSES_H From b4ef25dfa4614c3913282a0496ceda35308f6bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Thu, 8 Aug 2024 16:15:41 +0200 Subject: [PATCH 042/101] Document customizable fixit suggestions Co-authored-by: Manuel Pietsch --- ...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 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 ` guideline and is part of the `Bounds Safety (Bounds 4) -` profile +` 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 6c4b37ab2a0a3..8cdcb13e1b27b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -201,7 +201,7 @@ Clang-Tidy Checks :doc:`cppcoreguidelines-owning-memory `, :doc:`cppcoreguidelines-prefer-member-initializer `, "Yes" :doc:`cppcoreguidelines-pro-bounds-array-to-pointer-decay `, - :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses `, + :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses `, "Yes" :doc:`cppcoreguidelines-pro-bounds-constant-array-index `, "Yes" :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic `, :doc:`cppcoreguidelines-pro-type-const-cast `, From 12c3aa18cd9bbc1cc97a0dad7d079f71a12982b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Thu, 8 Aug 2024 16:10:46 +0200 Subject: [PATCH 043/101] Test customizable fixit suggestions Co-authored-by: Manuel Pietsch --- ...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 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 @@ -69,49 +86,96 @@ class ExcludedClass2 { } }; +template int f(T, unsigned){ return 0;} +template int f(T){ return 0;} + std::array 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 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 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 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 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 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 int TestTemplate(T t){ auto v = TestTemplate<>(a); auto w = TestTemplate<>(p); -std::map 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 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 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 a48facee1f35e3df98363ab0edbe58951f48a83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 26 Oct 2024 20:56:56 +0200 Subject: [PATCH 044/101] Update one-sentence description of `cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses` check Co-authored-by: Manuel Pietsch --- .../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 c84072edee0cd..9bbd4771fc53b 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -121,7 +121,8 @@ New checks - New :doc:`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:`llvm-mlir-op-builder ` 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 e7a0e89fdc51a78a69b36eead4ee3e1ca062a4cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 26 Oct 2024 21:01:59 +0200 Subject: [PATCH 045/101] Format description of the `cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses` in ReleaseNotes.rst Co-authored-by: Manuel Pietsch --- 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 9bbd4771fc53b..e43d8dd77730f 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -118,8 +118,9 @@ New checks Detects default initialization (to 0) of variables with ``enum`` type where the enum has no enumerator with value of 0. -- New :doc:`cppcoreguidelines-avoid-bounds-errors - ` check. +- New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses + ` + check. Flags calls to operator[] in STL containers and suggests replacing it with safe alternatives. From 60a01be3c92222c11989d08eeb5d0e6e307a80f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 26 Oct 2024 21:06:26 +0200 Subject: [PATCH 046/101] Generalise description of excluded classes in `pro-bounds-avoid-unchecked-container-accesses.rst` Co-authored-by: Manuel Pietsch --- .../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 ` From 8d20083252aa2e3641fdd8488d2c2f12e89feda4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 26 Oct 2024 21:21:47 +0200 Subject: [PATCH 047/101] s/bound-safe/bounds-safe Co-authored-by: Manuel Pietsch --- ...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 int f(T){ return 0;} std::array 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 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 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 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 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 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 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 4aabe8eac85ebedf9f6ed5dd9cf02a63ad63c67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 4 Nov 2024 11:13:02 +0100 Subject: [PATCH 048/101] docs: remove whitespace Co-authored-by: Manuel Pietsch --- .../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 df68ad3ea58dd27117c8acfdf5d93fa5d2662cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 5 Nov 2024 10:33:45 +0100 Subject: [PATCH 049/101] Update clang-tools-extra/docs/ReleaseNotes.rst Co-authored-by: EugeneZelenko --- 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 e43d8dd77730f..b48615fdab9c5 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -122,7 +122,7 @@ New checks ` 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:`llvm-mlir-op-builder From 7fa4e81d22317f141f0ef168e4f5369095520d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 5 Nov 2024 10:34:34 +0100 Subject: [PATCH 050/101] Update clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: EugeneZelenko --- .../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 02bddefe61cb7249f60c096c8d72106b472e4062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 5 Nov 2024 10:34:53 +0100 Subject: [PATCH 051/101] Update clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: EugeneZelenko --- .../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 e897d104da3408c79d471551e59a4bd3755850d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 5 Nov 2024 10:41:43 +0100 Subject: [PATCH 052/101] Update clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: EugeneZelenko --- .../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 7d4f6be48e65167600007193d5cb25c41c4339ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Fri, 14 Feb 2025 11:37:13 +0100 Subject: [PATCH 053/101] SubscriptExcludeClasses -> ExcludeClasses Co-authored-by: Manuel Pietsch --- .../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 c22b8998a8555c191f7f569ed6aa4b9a72ed78c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 15 Feb 2025 13:00:08 +0100 Subject: [PATCH 054/101] SubscriptFixMode -> FixMode Co-authored-by: Manuel Pietsch --- ...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("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("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(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(MCE->getCallee()); std::string BeginInsertion = SubscriptFixFunction.str() + "("; @@ -241,9 +241,9 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( namespace clang::tidy { using P = cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses; -llvm::ArrayRef> -OptionEnumMapping::getEnumMapping() { - static constexpr std::pair Mapping[] = { +llvm::ArrayRef> +OptionEnumMapping::getEnumMapping() { + static constexpr std::pair 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 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::FixModes> { + static ArrayRef> 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 b3220986ff31257c1a2299f71a62baaafc7924b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 15 Feb 2025 13:03:38 +0100 Subject: [PATCH 055/101] SubscriptFixFunction -> FixFunction Co-authored-by: Manuel Pietsch --- .../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(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 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 From dcd1935cb2a36f0124593411192ddc5ec27f6bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 15 Feb 2025 13:05:54 +0100 Subject: [PATCH 056/101] Remove "Subscript" prefix for variable names Co-authored-by: Manuel Pietsch --- ...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 SubscriptDefaultExclusions = { +static constexpr std::array 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 SubscriptExcludedClasses; + std::vector ExcludedClasses; // Setting which fix to suggest FixModes FixMode; llvm::StringRef FixFunction; From 0784a478cd1766cf54574dc15c502432f5b3d836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 15 Feb 2025 13:06:39 +0100 Subject: [PATCH 057/101] Update clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: EugeneZelenko --- .../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 612eb35467d948cc6c2e7d0ce842d0a5f8722d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 15 Feb 2025 13:06:56 +0100 Subject: [PATCH 058/101] Update clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: EugeneZelenko --- .../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 a47409258efc73cdea6bed88a8d9542ffdbacbd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 15 Feb 2025 13:09:08 +0100 Subject: [PATCH 059/101] 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 --- .../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 ea45352f6323c19c212dd74917b0e858d073b701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 15 Feb 2025 13:19:47 +0100 Subject: [PATCH 060/101] Remove contradicting "but" in cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: Manuel Pietsch --- .../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 a; int b = a[4]; -will generate a warning but +and .. code-block:: c++ From a523bf34262269eea90e78e52cfabd71935f33ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 17 Feb 2025 09:22:19 +0100 Subject: [PATCH 061/101] Only match subscript operators with a parameter list of size 0 or 1 Co-authored-by: Manuel Pietsch --- .../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 f02f22ec5df39c4ab66f2511831d941629ce50a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 17 Feb 2025 10:47:58 +0100 Subject: [PATCH 062/101] Simplify how user-specified excluded classes are stored Co-authored-by: Manuel Pietsch --- ...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 ExcludedClasses; + llvm::StringRef ExcludedClassesStr; // Setting which fix to suggest FixModes FixMode; llvm::StringRef FixFunction; From 202595372bfaba7eebdff16521ab285f7a90481c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Thu, 8 May 2025 12:02:30 +0200 Subject: [PATCH 063/101] Remove unused import Co-authored-by: Manuel Pietsch --- .../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 using namespace clang::ast_matchers; From 226aa8d84a345b2af7885d4e4325cc6ecf330c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 10 May 2025 19:00:29 +0200 Subject: [PATCH 064/101] Make FixMode "none" lowercase Co-authored-by: Manuel Pietsch --- .../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> OptionEnumMapping::getEnumMapping() { static constexpr std::pair 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 801ad8f53c4303c48638137d7702525524c78471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sun, 11 May 2025 14:43:51 +0200 Subject: [PATCH 065/101] Separate C++23 tests Co-authored-by: Manuel Pietsch --- ...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 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 4d1aa5afc59a911f8d84e211eede5a5f75858f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 16:15:47 +0200 Subject: [PATCH 066/101] Change semantics around excluded classes The ExcludedClasses option now overwrites the default exclusions and does not extend them. Co-authored-by: Manuel Pietsch --- .../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 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 6d30c8ddaec8e0c39c3f4f19436caa21b39fa2cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 16:16:31 +0200 Subject: [PATCH 067/101] Add tests for new "ExcludedClasses" semantics and split tests into separate fiels with split-file Co-authored-by: Manuel Pietsch --- ...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 @@ -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 {}; +//--- 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 {}; template int f(T, unsigned){ return 0;} template 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 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 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 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 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 + struct array_cxx_23 { + T operator[]() { + return T{1}; + } + T at() { + return T{1}; + } + }; +}; + +std::array_cxx_23 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 From cba734c77ae15b116513678749e2d8281715180b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 18:43:34 +0200 Subject: [PATCH 068/101] Update clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp Co-authored-by: Baranov Victor --- .../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 0e6fd88ab9218..0c7117c702a8f 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -23,7 +23,6 @@ ProBoundsAvoidUncheckedContainerAccesses:: ProBoundsAvoidUncheckedContainerAccesses(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) { - ExcludedClassesStr = Options.get("ExcludeClasses", DefaultExclusionStr); ExcludedClasses = clang::tidy::utils::options::parseStringList(ExcludedClassesStr); From a419064c739f1f137379916681417e2826144ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 19:57:28 +0200 Subject: [PATCH 069/101] Update clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp Co-authored-by: Baranov Victor --- .../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 0c7117c702a8f..a12aeec626669 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -117,7 +117,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( // Case: a[i] auto LeftBracket = SourceRange(OCE->getCallee()->getBeginLoc(), OCE->getCallee()->getBeginLoc()); - auto RightBracket = + const auto RightBracket = SourceRange(OCE->getOperatorLoc(), OCE->getOperatorLoc()); if (FixMode == At) { From 97aa6a4f9b92fea6dd51558aad94236990621969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 19:57:48 +0200 Subject: [PATCH 070/101] Update clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp Co-authored-by: Baranov Victor --- .../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 a12aeec626669..e11a19482dcc4 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -115,7 +115,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( if (const auto *OCE = dyn_cast(MatchedExpr)) { // Case: a[i] - auto LeftBracket = SourceRange(OCE->getCallee()->getBeginLoc(), + const auto LeftBracket = SourceRange(OCE->getCallee()->getBeginLoc(), OCE->getCallee()->getBeginLoc()); const auto RightBracket = SourceRange(OCE->getOperatorLoc(), OCE->getOperatorLoc()); From f509f6db07531b4647cd1147698a08620a3a9de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 19:58:06 +0200 Subject: [PATCH 071/101] Update clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst Co-authored-by: Baranov Victor --- .../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 9832c0706129a..a29f47650566c 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 @@ -38,7 +38,7 @@ Options Semicolon-delimited list of class names for overwriting the default exclusion list. The default is: - ``::std::map;::std::unordered_map;::std::flat_map``. + `::std::map;::std::unordered_map;::std::flat_map`. .. option:: FixMode From c5ec18a14b7b6ec316d73b70a0b135a0d58e186f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 20:01:11 +0200 Subject: [PATCH 072/101] s/flags/finds in docs Co-authored-by: Manuel Pietsch --- clang-tools-extra/docs/ReleaseNotes.rst | 4 ++-- .../pro-bounds-avoid-unchecked-container-accesses.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index b48615fdab9c5..bb12804944763 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -122,8 +122,8 @@ New checks ` check. - Flags calls to ``operator[]`` in STL containers and suggests replacing it with - safe alternatives. + Finds calls to ``operator[]`` in STL containers and suggests replacing them + with safe alternatives. - New :doc:`llvm-mlir-op-builder ` 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 a29f47650566c..2bc5f3758864d 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 calls to ``operator[]`` in STL containers and suggests replacing it with -safe alternatives. +Finds calls to ``operator[]`` in STL containers and suggests replacing them +with safe alternatives. For example, both From 023df9d75fbb2dc72ef7007674dcacc5eae98de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 20:03:14 +0200 Subject: [PATCH 073/101] Mention default option at end of description in docs Co-authored-by: Manuel Pietsch --- .../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 2bc5f3758864d..be35057204385 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,9 +42,9 @@ Options .. option:: FixMode - Determines what fixes are suggested. Either `none` (default), `at` (use + Determines what fixes are suggested. Either `none`, `at` (use ``a.at(index)`` if a fitting function exists) or `function` (use a - function ``f(a, index)``). + function ``f(a, index)``). The default is `none`. .. option:: FixFunction From c233df38114000b9602926b203a1fd74d229afb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 20:13:30 +0200 Subject: [PATCH 074/101] Refactor `ExcludedClassesStr` Co-authored-by: Manuel Pietsch --- .../ProBoundsAvoidUncheckedContainerAccesses.cpp | 8 ++++---- .../ProBoundsAvoidUncheckedContainerAccesses.h | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp index e11a19482dcc4..ade6249ac3dd1 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -23,9 +23,8 @@ ProBoundsAvoidUncheckedContainerAccesses:: ProBoundsAvoidUncheckedContainerAccesses(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) { - ExcludedClassesStr = Options.get("ExcludeClasses", DefaultExclusionStr); - ExcludedClasses = - clang::tidy::utils::options::parseStringList(ExcludedClassesStr); + ExcludedClasses = utils::options::parseStringList( + Options.get("ExcludeClasses", DefaultExclusionStr)); FixMode = Options.get("FixMode", None); FixFunction = Options.get("FixFunction", "gsl::at"); } @@ -35,7 +34,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions( Options.store(Opts, "FixFunction", FixFunction); Options.store(Opts, "FixMode", FixMode); - Options.store(Opts, "ExcludeClasses", ExcludedClassesStr); + Options.store(Opts, "ExcludeClasses", + utils::options::serializeStringList(ExcludedClasses)); } // 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 b18f4e14e62b8..f0d4a15cf64fe 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h @@ -36,7 +36,6 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck { private: // A list of class names that are excluded from the warning std::vector ExcludedClasses; - llvm::StringRef ExcludedClassesStr; // Setting which fix to suggest FixModes FixMode; llvm::StringRef FixFunction; From ce215ebbd24db973cecd5b244a6d714c8a42d27d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 27 May 2025 20:13:51 +0200 Subject: [PATCH 075/101] Formatting Co-authored-by: Manuel Pietsch --- .../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 ade6249ac3dd1..966a69d267fea 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -116,7 +116,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( if (const auto *OCE = dyn_cast(MatchedExpr)) { // Case: a[i] const auto LeftBracket = SourceRange(OCE->getCallee()->getBeginLoc(), - OCE->getCallee()->getBeginLoc()); + OCE->getCallee()->getBeginLoc()); const auto RightBracket = SourceRange(OCE->getOperatorLoc(), OCE->getOperatorLoc()); From 0109ec42adfcb19202d373181d62eb68d61c7eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Thu, 19 Jun 2025 14:45:36 +0200 Subject: [PATCH 076/101] Fix tests --- .../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 966a69d267fea..f5166a66ec0a2 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -151,7 +151,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( "possibly unsafe 'operator[]', use safe function '" + FixFunction.str() + "()' instead") << MatchedExpr->getCallee()->getSourceRange() - << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), + << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), FixFunction.str() + "(") // Since C++23, the subscript operator may also be called without an // argument, which makes the following distinction necessary From db38dc2793473ac868028d33e1713893b30c3915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 7 Jul 2025 14:07:37 +0200 Subject: [PATCH 077/101] Initialise ProBoundsAvoidUncheckedContainerAccesses members in initialiser list --- .../ProBoundsAvoidUncheckedContainerAccesses.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp index f5166a66ec0a2..f896cd6ea5f19 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -22,12 +22,11 @@ static constexpr llvm::StringRef DefaultExclusionStr = ProBoundsAvoidUncheckedContainerAccesses:: ProBoundsAvoidUncheckedContainerAccesses(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) { - ExcludedClasses = utils::options::parseStringList( - Options.get("ExcludeClasses", DefaultExclusionStr)); - FixMode = Options.get("FixMode", None); - FixFunction = Options.get("FixFunction", "gsl::at"); -} + : ClangTidyCheck(Name, Context), + ExcludedClasses(utils::options::parseStringList( + Options.get("ExcludeClasses", DefaultExclusionStr))), + FixMode(Options.get("FixMode", None)), + FixFunction(Options.get("FixFunction", "gsl::at")) {} void ProBoundsAvoidUncheckedContainerAccesses::storeOptions( ClangTidyOptions::OptionMap &Opts) { From 94aac087a8ea3f9f3bf3443586051ec5cf21ccf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 7 Jul 2025 21:05:36 +0200 Subject: [PATCH 078/101] docs: outline examples of safe alterantives to subscript operator --- .../pro-bounds-avoid-unchecked-container-accesses.rst | 3 +++ 1 file changed, 3 insertions(+) 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 be35057204385..86cdd10991202 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 @@ -5,6 +5,9 @@ cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses Finds calls to ``operator[]`` in STL containers and suggests replacing them with safe alternatives. +Safe alternatives include STL ``at`` or GSL ``at`` functions, ``begin()`` or +``end()`` functions, ``range-for`` loops, ``std::span``, or an appropriate +function from ````. For example, both From c805a8600e1a22410daff95fa5c46909f21bfad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 8 Jul 2025 12:12:50 +0200 Subject: [PATCH 079/101] Reorder `Option.store`s and remove empty line --- .../ProBoundsAvoidUncheckedContainerAccesses.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp index f896cd6ea5f19..2c7f9a5c401dd 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -30,11 +30,10 @@ ProBoundsAvoidUncheckedContainerAccesses:: void ProBoundsAvoidUncheckedContainerAccesses::storeOptions( ClangTidyOptions::OptionMap &Opts) { - - Options.store(Opts, "FixFunction", FixFunction); - Options.store(Opts, "FixMode", FixMode); Options.store(Opts, "ExcludeClasses", utils::options::serializeStringList(ExcludedClasses)); + Options.store(Opts, "FixMode", FixMode); + Options.store(Opts, "FixFunction", FixFunction); } // TODO: if at() is defined in another class in the class hierarchy of the class From eb9d841a0cc42a5d2c2f7f99bf4281fb937f657d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 8 Jul 2025 13:47:22 +0200 Subject: [PATCH 080/101] Add FixFunctionEmptyArgs option --- ...oBoundsAvoidUncheckedContainerAccesses.cpp | 89 ++++++++++++------- ...ProBoundsAvoidUncheckedContainerAccesses.h | 1 + ...nds-avoid-unchecked-container-accesses.rst | 12 ++- ...nds-avoid-unchecked-container-accesses.cpp | 16 ++++ 4 files changed, 86 insertions(+), 32 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp index 2c7f9a5c401dd..3adc5a31e8956 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -26,7 +26,8 @@ ProBoundsAvoidUncheckedContainerAccesses:: ExcludedClasses(utils::options::parseStringList( Options.get("ExcludeClasses", DefaultExclusionStr))), FixMode(Options.get("FixMode", None)), - FixFunction(Options.get("FixFunction", "gsl::at")) {} + FixFunction(Options.get("FixFunction", "gsl::at")), + FixFunctionEmptyArgs(Options.get("FixFunctionEmptyArgs", FixFunction)) {} void ProBoundsAvoidUncheckedContainerAccesses::storeOptions( ClangTidyOptions::OptionMap &Opts) { @@ -34,6 +35,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::storeOptions( utils::options::serializeStringList(ExcludedClasses)); Options.store(Opts, "FixMode", FixMode); Options.store(Opts, "FixFunction", FixFunction); + Options.store(Opts, "FixFunctionEmptyArgs", FixFunctionEmptyArgs); } // TODO: if at() is defined in another class in the class hierarchy of the class @@ -145,18 +147,30 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( } else if (FixMode == Function) { // Case: a[i] => f(a, i) - diag(MatchedExpr->getCallee()->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '" + - FixFunction.str() + "()' instead") - << MatchedExpr->getCallee()->getSourceRange() - << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), - 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 - ? FixItHint::CreateReplacement(LeftBracket, ", ") - : FixItHint::CreateRemoval(LeftBracket)) - << FixItHint::CreateReplacement(RightBracket, ")"); + // + // Since C++23, the subscript operator may also be called without an + // argument, which makes the following distinction necessary + bool EmptySubscript = MatchedExpr->getDirectCallee()->getNumParams() == 0; + + if (EmptySubscript) { + diag(MatchedExpr->getCallee()->getBeginLoc(), + "possibly unsafe 'operator[]', use safe function '" + + FixFunctionEmptyArgs.str() + "()' instead") + << MatchedExpr->getCallee()->getSourceRange() + << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), + FixFunctionEmptyArgs.str() + "(") + << FixItHint::CreateRemoval(LeftBracket) + << FixItHint::CreateReplacement(RightBracket, ")"); + } else { + diag(MatchedExpr->getCallee()->getBeginLoc(), + "possibly unsafe 'operator[]', use safe function '" + + FixFunction.str() + "()' instead") + << MatchedExpr->getCallee()->getSourceRange() + << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), + FixFunction.str() + "(") + << FixItHint::CreateReplacement(LeftBracket, ", ") + << FixItHint::CreateReplacement(RightBracket, ")"); + } } } else if (const auto *MCE = dyn_cast(MatchedExpr)) { // Case: a.operator[](i) or a->operator[](i) @@ -189,28 +203,41 @@ 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(MCE->getCallee()); - std::string BeginInsertion = FixFunction.str() + "("; + + bool EmptySubscript = MCE->getMethodDecl()->getNumNonObjectParams() == 0; + + std::string BeginInsertion = + (EmptySubscript ? FixFunctionEmptyArgs.str() : FixFunction.str()) + + "("; if (Callee->isArrow()) BeginInsertion += "*"; - diag(Callee->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '" + - FixFunction.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)))); + // Since C++23, the subscript operator may also be called without an + // argument, which makes the following distinction necessary + if (EmptySubscript) { + diag(Callee->getBeginLoc(), + "possibly unsafe 'operator[]', use safe function '" + + FixFunctionEmptyArgs.str() + "()' instead") + << Callee->getSourceRange() + << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), + BeginInsertion) + << FixItHint::CreateRemoval( + SourceRange(Callee->getOperatorLoc(), + MCE->getRParenLoc().getLocWithOffset(-1))); + } else { + diag(Callee->getBeginLoc(), + "possibly unsafe 'operator[]', use safe function '" + + FixFunction.str() + "()' instead") + << Callee->getSourceRange() + << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), + BeginInsertion) + << FixItHint::CreateReplacement( + SourceRange( + Callee->getOperatorLoc(), + MCE->getArg(0)->getBeginLoc().getLocWithOffset(-1)), + ", "); + } } } } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h index f0d4a15cf64fe..07062114e73a9 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h @@ -39,6 +39,7 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck { // Setting which fix to suggest FixModes FixMode; llvm::StringRef FixFunction; + llvm::StringRef FixFunctionEmptyArgs; }; } // 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 86cdd10991202..7f0d957043c50 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 @@ -51,4 +51,14 @@ 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. For C++23 + and beyond, the passed function must support the empty subscript operator, + i.e., the case where ``a[]`` becomes ``f(a)``. The `FixFunctionEmptyArgs` + option can be used to override the suggested function in that case. + +.. option:: FixFunctionEmptyArgs + + The function to use in the `function` mode for the empty subscript operator + case in C++23 and beyond only. Defaults to the value of `FixFunction`. If + no fixes should be made for empty subscript operators, pass an empty + string. 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 32b48309122cc..4bd802e15d6b8 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 @@ -59,6 +59,16 @@ // 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 +// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC-EMPTY-ARGS-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", cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunctionEmptyArgs: "g", }}' -- -I%t -DCXX_23=1 + +// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC-EMPTY-ARGS-EMPTY-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.FixFunctionEmptyArgs: "", }}' -- -I%t -DCXX_23=1 + //--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h namespace std { @@ -309,14 +319,20 @@ 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); +// CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto b23 = g(a); +// CHECK-FIXES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] 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)); +// CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fa23 = g(*(&a)); +// CHECK-FIXES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] 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); +// CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fd23 = g(a); +// CHECK-FIXES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] #endif From b2d78fb1e4433401d647d8e284af787ce75e6b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 8 Jul 2025 15:51:37 +0200 Subject: [PATCH 081/101] Update clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp Co-authored-by: EugeneZelenko --- .../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 3adc5a31e8956..f73865a3c0138 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -150,7 +150,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( // // Since C++23, the subscript operator may also be called without an // argument, which makes the following distinction necessary - bool EmptySubscript = MatchedExpr->getDirectCallee()->getNumParams() == 0; + const bool EmptySubscript = MatchedExpr->getDirectCallee()->getNumParams() == 0; if (EmptySubscript) { diag(MatchedExpr->getCallee()->getBeginLoc(), From 1c06763cb8dbf71593a8bb67598cad1dbeb56bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 8 Jul 2025 15:51:49 +0200 Subject: [PATCH 082/101] Update clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp Co-authored-by: EugeneZelenko --- .../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 f73865a3c0138..b486fa0a1e349 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -204,7 +204,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( // Cases: a.operator[](i) => f(a, i) and a->operator[](i) => f(*a, i) const auto *Callee = dyn_cast(MCE->getCallee()); - bool EmptySubscript = MCE->getMethodDecl()->getNumNonObjectParams() == 0; + const bool EmptySubscript = MCE->getMethodDecl()->getNumNonObjectParams() == 0; std::string BeginInsertion = (EmptySubscript ? FixFunctionEmptyArgs.str() : FixFunction.str()) + From de2b199a4580b89f811d4d1e812a70973b24e405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 8 Jul 2025 18:32:43 +0200 Subject: [PATCH 083/101] Format --- .../ProBoundsAvoidUncheckedContainerAccesses.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp index b486fa0a1e349..ae3071fcfa818 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -150,7 +150,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( // // Since C++23, the subscript operator may also be called without an // argument, which makes the following distinction necessary - const bool EmptySubscript = MatchedExpr->getDirectCallee()->getNumParams() == 0; + const bool EmptySubscript = + MatchedExpr->getDirectCallee()->getNumParams() == 0; if (EmptySubscript) { diag(MatchedExpr->getCallee()->getBeginLoc(), @@ -204,7 +205,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( // Cases: a.operator[](i) => f(a, i) and a->operator[](i) => f(*a, i) const auto *Callee = dyn_cast(MCE->getCallee()); - const bool EmptySubscript = MCE->getMethodDecl()->getNumNonObjectParams() == 0; + const bool EmptySubscript = + MCE->getMethodDecl()->getNumNonObjectParams() == 0; std::string BeginInsertion = (EmptySubscript ? FixFunctionEmptyArgs.str() : FixFunction.str()) + From e18eeacb02fab0f00ae9fafb0cd398c00ff266f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Wed, 9 Jul 2025 09:21:06 +0200 Subject: [PATCH 084/101] Use `%` formatting for diagnostics --- ...oBoundsAvoidUncheckedContainerAccesses.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp index ae3071fcfa818..ef1bab073bd50 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -155,8 +155,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( if (EmptySubscript) { diag(MatchedExpr->getCallee()->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '" + - FixFunctionEmptyArgs.str() + "()' instead") + "possibly unsafe 'operator[]', use safe function '%s()' instead") + << FixFunctionEmptyArgs.str() << MatchedExpr->getCallee()->getSourceRange() << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), FixFunctionEmptyArgs.str() + "(") @@ -164,9 +164,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( << FixItHint::CreateReplacement(RightBracket, ")"); } else { diag(MatchedExpr->getCallee()->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '" + - FixFunction.str() + "()' instead") - << MatchedExpr->getCallee()->getSourceRange() + "possibly unsafe 'operator[]', use safe function '%s()' instead") + << FixFunction.str() << MatchedExpr->getCallee()->getSourceRange() << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), FixFunction.str() + "(") << FixItHint::CreateReplacement(LeftBracket, ", ") @@ -219,9 +218,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( // argument, which makes the following distinction necessary if (EmptySubscript) { diag(Callee->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '" + - FixFunctionEmptyArgs.str() + "()' instead") - << Callee->getSourceRange() + "possibly unsafe 'operator[]', use safe function '%s()' instead") + << FixFunctionEmptyArgs.str() << Callee->getSourceRange() << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), BeginInsertion) << FixItHint::CreateRemoval( @@ -229,9 +227,8 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( MCE->getRParenLoc().getLocWithOffset(-1))); } else { diag(Callee->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '" + - FixFunction.str() + "()' instead") - << Callee->getSourceRange() + "possibly unsafe 'operator[]', use safe function '%s()' instead") + << FixFunction.str() << Callee->getSourceRange() << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), BeginInsertion) << FixItHint::CreateReplacement( From 5ffcfdb112e8367308cf371d0196bf1c9455140c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Wed, 9 Jul 2025 09:30:29 +0200 Subject: [PATCH 085/101] docs: point out default values of options at the end of their description --- ...-bounds-avoid-unchecked-container-accesses.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 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 7f0d957043c50..c9f8c573edc2d 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 @@ -51,14 +51,15 @@ Options .. option:: FixFunction - The function to use in the `function` mode. `gsl::at` by default. For C++23 - and beyond, the passed function must support the empty subscript operator, - i.e., the case where ``a[]`` becomes ``f(a)``. The `FixFunctionEmptyArgs` - option can be used to override the suggested function in that case. + The function to use in the `function` mode. For C++23 and beyond, the + passed function must support the empty subscript operator, i.e., the case + where ``a[]`` becomes ``f(a)``. The `FixFunctionEmptyArgs` option can be + used to override the suggested function in that case. The default for + `FixFunction` is `gsl::at`. .. option:: FixFunctionEmptyArgs The function to use in the `function` mode for the empty subscript operator - case in C++23 and beyond only. Defaults to the value of `FixFunction`. If - no fixes should be made for empty subscript operators, pass an empty - string. + case in C++23 and beyond only. If no fixes should be made for empty + subscript operators, pass an empty string. The default is the value of + `FixFunction`. From 1d8100636aa13f40a174b0d1a597834ece233788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Wed, 9 Jul 2025 10:02:11 +0200 Subject: [PATCH 086/101] Fix format strings --- .../ProBoundsAvoidUncheckedContainerAccesses.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp index ef1bab073bd50..32915daa18218 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -155,7 +155,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( if (EmptySubscript) { diag(MatchedExpr->getCallee()->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '%s()' instead") + "possibly unsafe 'operator[]', use safe function '%0()' instead") << FixFunctionEmptyArgs.str() << MatchedExpr->getCallee()->getSourceRange() << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), @@ -164,7 +164,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( << FixItHint::CreateReplacement(RightBracket, ")"); } else { diag(MatchedExpr->getCallee()->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '%s()' instead") + "possibly unsafe 'operator[]', use safe function '%0()' instead") << FixFunction.str() << MatchedExpr->getCallee()->getSourceRange() << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), FixFunction.str() + "(") @@ -218,7 +218,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( // argument, which makes the following distinction necessary if (EmptySubscript) { diag(Callee->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '%s()' instead") + "possibly unsafe 'operator[]', use safe function '%0()' instead") << FixFunctionEmptyArgs.str() << Callee->getSourceRange() << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), BeginInsertion) @@ -227,7 +227,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( MCE->getRParenLoc().getLocWithOffset(-1))); } else { diag(Callee->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '%s()' instead") + "possibly unsafe 'operator[]', use safe function '%0()' instead") << FixFunction.str() << Callee->getSourceRange() << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), BeginInsertion) From e5d6c270a621504a0a01cd8306f220e7453da7e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Wed, 9 Jul 2025 10:13:03 +0200 Subject: [PATCH 087/101] Excplitly check for `FixFunctionEmptyArgs` option being empty --- ...oBoundsAvoidUncheckedContainerAccesses.cpp | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp index 32915daa18218..dd9989b2423b1 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -154,14 +154,16 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( MatchedExpr->getDirectCallee()->getNumParams() == 0; if (EmptySubscript) { - diag(MatchedExpr->getCallee()->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '%0()' instead") - << FixFunctionEmptyArgs.str() - << MatchedExpr->getCallee()->getSourceRange() - << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), - FixFunctionEmptyArgs.str() + "(") - << FixItHint::CreateRemoval(LeftBracket) - << FixItHint::CreateReplacement(RightBracket, ")"); + if (!FixFunctionEmptyArgs.empty()) { + diag(MatchedExpr->getCallee()->getBeginLoc(), + "possibly unsafe 'operator[]', use safe function '%0()' instead") + << FixFunctionEmptyArgs.str() + << MatchedExpr->getCallee()->getSourceRange() + << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), + FixFunctionEmptyArgs.str() + "(") + << FixItHint::CreateRemoval(LeftBracket) + << FixItHint::CreateReplacement(RightBracket, ")"); + } } else { diag(MatchedExpr->getCallee()->getBeginLoc(), "possibly unsafe 'operator[]', use safe function '%0()' instead") @@ -217,14 +219,16 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( // Since C++23, the subscript operator may also be called without an // argument, which makes the following distinction necessary if (EmptySubscript) { - diag(Callee->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '%0()' instead") - << FixFunctionEmptyArgs.str() << Callee->getSourceRange() - << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), - BeginInsertion) - << FixItHint::CreateRemoval( - SourceRange(Callee->getOperatorLoc(), - MCE->getRParenLoc().getLocWithOffset(-1))); + if (!FixFunctionEmptyArgs.empty()) { + diag(Callee->getBeginLoc(), + "possibly unsafe 'operator[]', use safe function '%0()' instead") + << FixFunctionEmptyArgs.str() << Callee->getSourceRange() + << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), + BeginInsertion) + << FixItHint::CreateRemoval( + SourceRange(Callee->getOperatorLoc(), + MCE->getRParenLoc().getLocWithOffset(-1))); + } } else { diag(Callee->getBeginLoc(), "possibly unsafe 'operator[]', use safe function '%0()' instead") From 581b8739b58e2d23aab6c9bbd51811060c8da4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Wed, 9 Jul 2025 10:13:31 +0200 Subject: [PATCH 088/101] Use CHECK-MESSAGES-NOT in `FixFunctionEmptyArgs` tests --- .../pro-bounds-avoid-unchecked-container-accesses.cpp | 6 +++--- 1 file changed, 3 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 4bd802e15d6b8..7c423370c7ad9 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 @@ -320,19 +320,19 @@ auto b23 = a[]; // CHECK-FIXES-AT-CXX-23: auto b23 = a.at(); // CHECK-FIXES-FUNC-CXX-23: auto b23 = f(a); // CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto b23 = g(a); -// CHECK-FIXES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] +// CHECK-MESSAGES-NOT: :[[@LINE-5]]:{{.*}}: note: FIX-IT applied suggested code changes 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)); // CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fa23 = g(*(&a)); -// CHECK-FIXES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] +// CHECK-MESSAGES-NOT: :[[@LINE-5]]:{{.*}}: note: FIX-IT applied suggested code changes 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); // CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fd23 = g(a); -// CHECK-FIXES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] +// CHECK-MESSAGES-NOT: :[[@LINE-5]]:{{.*}}: note: FIX-IT applied suggested code changes #endif From a4306af680f6cda6b617998bf63c7df7b27684f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 12 Jul 2025 12:24:10 +0200 Subject: [PATCH 089/101] Print warning when FixFunctionEmptyArgs is explicitly set to "", but don't suggest fixes --- ...oBoundsAvoidUncheckedContainerAccesses.cpp | 36 ++++++++++--------- ...nds-avoid-unchecked-container-accesses.rst | 4 +-- ...nds-avoid-unchecked-container-accesses.cpp | 11 +++--- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp index dd9989b2423b1..39c5038902a71 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp @@ -154,15 +154,16 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( MatchedExpr->getDirectCallee()->getNumParams() == 0; if (EmptySubscript) { + auto D = diag(MatchedExpr->getCallee()->getBeginLoc(), + "possibly unsafe 'operator[]'%select{, use safe " + "function '%1() instead|}0") + << FixFunctionEmptyArgs.empty() << FixFunctionEmptyArgs.str() + << MatchedExpr->getCallee()->getSourceRange(); if (!FixFunctionEmptyArgs.empty()) { - diag(MatchedExpr->getCallee()->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '%0()' instead") - << FixFunctionEmptyArgs.str() - << MatchedExpr->getCallee()->getSourceRange() - << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), - FixFunctionEmptyArgs.str() + "(") - << FixItHint::CreateRemoval(LeftBracket) - << FixItHint::CreateReplacement(RightBracket, ")"); + D << FixItHint::CreateInsertion(OCE->getArg(0)->getBeginLoc(), + FixFunctionEmptyArgs.str() + "(") + << FixItHint::CreateRemoval(LeftBracket) + << FixItHint::CreateReplacement(RightBracket, ")"); } } else { diag(MatchedExpr->getCallee()->getBeginLoc(), @@ -219,15 +220,18 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( // Since C++23, the subscript operator may also be called without an // argument, which makes the following distinction necessary if (EmptySubscript) { + auto D = diag(MatchedExpr->getCallee()->getBeginLoc(), + "possibly unsafe 'operator[]'%select{, use safe " + "function '%1()' instead|}0") + << FixFunctionEmptyArgs.empty() << FixFunctionEmptyArgs.str() + << Callee->getSourceRange(); + if (!FixFunctionEmptyArgs.empty()) { - diag(Callee->getBeginLoc(), - "possibly unsafe 'operator[]', use safe function '%0()' instead") - << FixFunctionEmptyArgs.str() << Callee->getSourceRange() - << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), - BeginInsertion) - << FixItHint::CreateRemoval( - SourceRange(Callee->getOperatorLoc(), - MCE->getRParenLoc().getLocWithOffset(-1))); + D << FixItHint::CreateInsertion(MatchedExpr->getBeginLoc(), + BeginInsertion) + << FixItHint::CreateRemoval( + SourceRange(Callee->getOperatorLoc(), + MCE->getRParenLoc().getLocWithOffset(-1))); } } else { diag(Callee->getBeginLoc(), 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 c9f8c573edc2d..7f4f418913d25 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 @@ -61,5 +61,5 @@ Options The function to use in the `function` mode for the empty subscript operator case in C++23 and beyond only. If no fixes should be made for empty - subscript operators, pass an empty string. The default is the value of - `FixFunction`. + subscript operators, pass an empty string. In that case, only the warnings + will be printed. The default is the value of `FixFunction`. 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 7c423370c7ad9..36ec8ac6f14c4 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 @@ -64,7 +64,7 @@ // RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixMode: function, \ // RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunction: "f", cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunctionEmptyArgs: "g", }}' -- -I%t -DCXX_23=1 -// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC-EMPTY-ARGS-EMPTY-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses-cxx-23.cpp \ +// RUN: %check_clang_tidy -std=c++23 -check-suffix=FUNC-EMPTY-ARGS-EMPTY-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.FixFunctionEmptyArgs: "", }}' -- -I%t -DCXX_23=1 @@ -320,19 +320,22 @@ auto b23 = a[]; // CHECK-FIXES-AT-CXX-23: auto b23 = a.at(); // CHECK-FIXES-FUNC-CXX-23: auto b23 = f(a); // CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto b23 = g(a); -// CHECK-MESSAGES-NOT: :[[@LINE-5]]:{{.*}}: note: FIX-IT applied suggested code changes +// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] +// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-6]]:{{.*}}: note: FIX-IT applied suggested code changes 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)); // CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fa23 = g(*(&a)); -// CHECK-MESSAGES-NOT: :[[@LINE-5]]:{{.*}}: note: FIX-IT applied suggested code changes +// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] +// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-6]]:{{.*}}: note: FIX-IT applied suggested code changes 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); // CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fd23 = g(a); -// CHECK-MESSAGES-NOT: :[[@LINE-5]]:{{.*}}: note: FIX-IT applied suggested code changes +// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] +// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-6]]:{{.*}}: note: FIX-IT applied suggested code changes #endif From c512fdf5beefa3abe70206cfc1249578d69df3b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 12 Jul 2025 12:32:19 +0200 Subject: [PATCH 090/101] docs: reword paragraph about the STL containers which are excluded by default --- .../pro-bounds-avoid-unchecked-container-accesses.rst | 6 ++++-- 1 file changed, 4 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 7f4f418913d25..20ed31c491035 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,8 +25,10 @@ and will generate a warning. -STL containers with well-defined behavior for ``operator[]`` are excluded from this -check. +STL containers that do not access memory outside the memory allocated by the +container via ``operator[]`` are excluded from this check. Excluded classes, +including the STL containers excluded by default, can be customized via +:option:`ExcludedClasses`. This check enforces part of the `SL.con.3 ` From f23a48cb4149d1e3c565f5c92a8edd860d4439e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 12 Jul 2025 12:34:15 +0200 Subject: [PATCH 091/101] docs: use :option:... syntax in FixFunction documentation --- .../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 20ed31c491035..5ce2c1e072238 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 @@ -55,7 +55,7 @@ Options The function to use in the `function` mode. For C++23 and beyond, the passed function must support the empty subscript operator, i.e., the case - where ``a[]`` becomes ``f(a)``. The `FixFunctionEmptyArgs` option can be + where ``a[]`` becomes ``f(a)``. :option:`FixFunctionEmptyArgs` can be used to override the suggested function in that case. The default for `FixFunction` is `gsl::at`. From b70899ddaf352572193f9421f1000c884fe8e891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 12 Jul 2025 13:15:55 +0200 Subject: [PATCH 092/101] docs: fix typo --- .../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 5ce2c1e072238..f0e9d74a57fe6 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 @@ -28,7 +28,7 @@ will generate a warning. STL containers that do not access memory outside the memory allocated by the container via ``operator[]`` are excluded from this check. Excluded classes, including the STL containers excluded by default, can be customized via -:option:`ExcludedClasses`. +:option:`ExcludeClasses`. This check enforces part of the `SL.con.3 ` From 77256f7bf0910d9df5793b6bd06b3f2f8c7b07aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 12 Jul 2025 13:37:03 +0200 Subject: [PATCH 093/101] s/accesses/access in check name --- .../cppcoreguidelines/CMakeLists.txt | 2 +- .../CppCoreGuidelinesTidyModule.cpp | 6 +- ...roBoundsAvoidUncheckedContainerAccess.cpp} | 15 +- ... ProBoundsAvoidUncheckedContainerAccess.h} | 20 +- clang-tools-extra/docs/ReleaseNotes.rst | 4 +- ...unds-avoid-unchecked-container-access.rst} | 6 +- .../docs/clang-tidy/checks/list.rst | 2 +- ...unds-avoid-unchecked-container-access.cpp} | 174 +++++++++--------- 8 files changed, 114 insertions(+), 115 deletions(-) rename clang-tools-extra/clang-tidy/cppcoreguidelines/{ProBoundsAvoidUncheckedContainerAccesses.cpp => ProBoundsAvoidUncheckedContainerAccess.cpp} (96%) rename clang-tools-extra/clang-tidy/cppcoreguidelines/{ProBoundsAvoidUncheckedContainerAccesses.h => ProBoundsAvoidUncheckedContainerAccess.h} (73%) rename clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/{pro-bounds-avoid-unchecked-container-accesses.rst => pro-bounds-avoid-unchecked-container-access.rst} (93%) rename clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/{pro-bounds-avoid-unchecked-container-accesses.cpp => pro-bounds-avoid-unchecked-container-access.cpp} (79%) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt index b7da037b8d8bc..0abb000991859 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -21,7 +21,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule STATIC OwningMemoryCheck.cpp PreferMemberInitializerCheck.cpp ProBoundsArrayToPointerDecayCheck.cpp - ProBoundsAvoidUncheckedContainerAccesses.cpp + ProBoundsAvoidUncheckedContainerAccess.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 f2a356f9e9ba3..cc1ae156eef3e 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -36,7 +36,7 @@ #include "OwningMemoryCheck.h" #include "PreferMemberInitializerCheck.h" #include "ProBoundsArrayToPointerDecayCheck.h" -#include "ProBoundsAvoidUncheckedContainerAccesses.h" +#include "ProBoundsAvoidUncheckedContainerAccess.h" #include "ProBoundsConstantArrayIndexCheck.h" #include "ProBoundsPointerArithmeticCheck.h" #include "ProTypeConstCastCheck.h" @@ -108,8 +108,8 @@ class CppCoreGuidelinesModule : public ClangTidyModule { "cppcoreguidelines-prefer-member-initializer"); CheckFactories.registerCheck( "cppcoreguidelines-pro-bounds-array-to-pointer-decay"); - CheckFactories.registerCheck( - "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses"); + CheckFactories.registerCheck( + "cppcoreguidelines-pro-bounds-avoid-unchecked-container-access"); CheckFactories.registerCheck( "cppcoreguidelines-pro-bounds-constant-array-index"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp similarity index 96% rename from clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp rename to clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp index 39c5038902a71..617e02daedf3c 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "ProBoundsAvoidUncheckedContainerAccesses.h" +#include "ProBoundsAvoidUncheckedContainerAccess.h" #include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -19,9 +19,8 @@ namespace clang::tidy::cppcoreguidelines { static constexpr llvm::StringRef DefaultExclusionStr = "::std::map;::std::unordered_map;::std::flat_map"; -ProBoundsAvoidUncheckedContainerAccesses:: - ProBoundsAvoidUncheckedContainerAccesses(StringRef Name, - ClangTidyContext *Context) +ProBoundsAvoidUncheckedContainerAccess::ProBoundsAvoidUncheckedContainerAccess( + StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), ExcludedClasses(utils::options::parseStringList( Options.get("ExcludeClasses", DefaultExclusionStr))), @@ -29,7 +28,7 @@ ProBoundsAvoidUncheckedContainerAccesses:: FixFunction(Options.get("FixFunction", "gsl::at")), FixFunctionEmptyArgs(Options.get("FixFunctionEmptyArgs", FixFunction)) {} -void ProBoundsAvoidUncheckedContainerAccesses::storeOptions( +void ProBoundsAvoidUncheckedContainerAccess::storeOptions( ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "ExcludeClasses", utils::options::serializeStringList(ExcludedClasses)); @@ -87,7 +86,7 @@ findAlternativeAt(const CXXMethodDecl *MatchedOperator) { return nullptr; } -void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers( +void ProBoundsAvoidUncheckedContainerAccess::registerMatchers( MatchFinder *Finder) { Finder->addMatcher( mapAnyOf(cxxOperatorCallExpr, cxxMemberCallExpr) @@ -101,7 +100,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers( this); } -void ProBoundsAvoidUncheckedContainerAccesses::check( +void ProBoundsAvoidUncheckedContainerAccess::check( const MatchFinder::MatchResult &Result) { const auto *MatchedExpr = Result.Nodes.getNodeAs("caller"); @@ -252,7 +251,7 @@ void ProBoundsAvoidUncheckedContainerAccesses::check( } // namespace clang::tidy::cppcoreguidelines namespace clang::tidy { -using P = cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses; +using P = cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccess; llvm::ArrayRef> OptionEnumMapping::getEnumMapping() { diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.h similarity index 73% rename from clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h rename to clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.h index 07062114e73a9..9fd0c922ed4c4 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccesses.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.h @@ -1,4 +1,4 @@ -//===--- ProBoundsAvoidUncheckedContainerAccesses.h - clang-tidy *- C++ -*-===// +//===--- ProBoundsAvoidUncheckedContainerAccess.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 +6,8 @@ // //===----------------------------------------------------------------------===// -#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 +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_AVOID_UNCHECKED_CONTAINER_ACCESS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_AVOID_UNCHECKED_CONTAINER_ACCESS_H #include "../ClangTidyCheck.h" @@ -19,11 +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/pro-bounds-avoid-unchecked-container-accesses.html -class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck { +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.html +class ProBoundsAvoidUncheckedContainerAccess : public ClangTidyCheck { public: - ProBoundsAvoidUncheckedContainerAccesses(StringRef Name, - ClangTidyContext *Context); + ProBoundsAvoidUncheckedContainerAccess(StringRef Name, + ClangTidyContext *Context); bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus; } @@ -46,11 +46,11 @@ class ProBoundsAvoidUncheckedContainerAccesses : public ClangTidyCheck { namespace clang::tidy { template <> struct OptionEnumMapping< - cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccesses::FixModes> { + cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccess::FixModes> { static ArrayRef> getEnumMapping(); }; } // namespace clang::tidy -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_AVOID_UNCHECKED_CONTAINER_ACCESSES_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_AVOID_UNCHECKED_CONTAINER_ACCESS_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index bb12804944763..6a65fc10089d0 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -118,8 +118,8 @@ New checks Detects default initialization (to 0) of variables with ``enum`` type where the enum has no enumerator with value of 0. -- New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses - ` +- New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-access + ` check. Finds calls to ``operator[]`` in STL containers and suggests replacing them 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-access.rst similarity index 93% rename from clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.rst rename to clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst index f0e9d74a57fe6..f05184e7bc4d6 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-access.rst @@ -1,7 +1,7 @@ -.. title:: clang-tidy - cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses +.. title:: clang-tidy - cppcoreguidelines-pro-bounds-avoid-unchecked-container-access -cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses -=============================================================== +cppcoreguidelines-pro-bounds-avoid-unchecked-container-access +============================================================= Finds calls to ``operator[]`` in STL containers and suggests replacing them with safe alternatives. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 8cdcb13e1b27b..d94a0b3bda596 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -201,7 +201,7 @@ Clang-Tidy Checks :doc:`cppcoreguidelines-owning-memory `, :doc:`cppcoreguidelines-prefer-member-initializer `, "Yes" :doc:`cppcoreguidelines-pro-bounds-array-to-pointer-decay `, - :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses `, "Yes" + :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-access `, "Yes" :doc:`cppcoreguidelines-pro-bounds-constant-array-index `, "Yes" :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic `, :doc:`cppcoreguidelines-pro-type-const-cast `, 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-access.cpp similarity index 79% rename from clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-accesses.cpp rename to clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.cpp index 36ec8ac6f14c4..30d03bd70edf6 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-access.cpp @@ -2,74 +2,74 @@ // 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=DEFAULT %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %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.FixMode: at}}' -- -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-access.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: at}}' -- -I%t -// 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.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 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunction: "f"}}' -- -I%t -// 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: ""}}' -- -I%t +// 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-access-no-excl.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.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=AT-NO-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-no-excl.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "", \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.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"}}' -- -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-access-no-excl.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "", \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunction: "f"}}' -- -I%t -// 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"}}' -- -I%t +// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=DEFAULT-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-excl.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "ExcludedClass1;ExcludedClass2"}}' -- -I%t -// 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}}' -- -I%t +// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=AT-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-excl.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "ExcludedClass1;ExcludedClass2", \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: at}}' -- -I%t -// 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: 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-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-excl.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "ExcludedClass1;ExcludedClass2", \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.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=DEFAULT-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %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=AT-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.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 +// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunction: "f"}}' -- -I%t -DCXX_23=1 -// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC-EMPTY-ARGS-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", cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.FixFunctionEmptyArgs: "g", }}' -- -I%t -DCXX_23=1 +// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC-EMPTY-ARGS-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunction: "f", cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunctionEmptyArgs: "g", }}' -- -I%t -DCXX_23=1 -// RUN: %check_clang_tidy -std=c++23 -check-suffix=FUNC-EMPTY-ARGS-EMPTY-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.FixFunctionEmptyArgs: "", }}' -- -I%t -DCXX_23=1 +// RUN: %check_clang_tidy -std=c++23 -check-suffix=FUNC-EMPTY-ARGS-EMPTY-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \ +// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \ +// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunctionEmptyArgs: "", }}' -- -I%t -DCXX_23=1 -//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h +//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h namespace std { template @@ -119,9 +119,9 @@ namespace json { }; } // namespace json -//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.cpp +//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.cpp -#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h" +#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h" struct SubClass : std::array {}; @@ -131,36 +131,36 @@ template int f(T){ return 0;} std::array a; auto b = a[0]; -// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-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-access] // CHECK-FIXES-AT: auto b = a.at(0); // CHECK-FIXES-FUNC: auto b = f(a, 0); 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-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // 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-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // 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 bounds-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-access] // 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 bounds-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-access] // 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 bounds-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-access] // CHECK-FIXES-AT: auto fd = a.at(1); // CHECK-FIXES-FUNC: auto fd = f(a, 1); @@ -170,38 +170,38 @@ auto g = a.at(0); std::unique_ptr p; auto q = p[0]; -// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-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-access] // CHECK-FIXES-AT: auto q = p[0]; // CHECK-FIXES-FUNC: auto q = f(p, 0); std::span s; auto t = s[0]; -// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-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-access] // CHECK-FIXES-AT: auto t = s[0]; // CHECK-FIXES-FUNC: auto t = f(s, 0); json::node n; auto m = n[0]; -// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-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-access] // 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 bounds-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-access] // CHECK-FIXES-AT: auto r = Sub.at(0); // CHECK-FIXES-FUNC: auto r = f(Sub, 0); typedef std::array ar; ar BehindDef; auto u = BehindDef[0]; -// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:19: warning: possibly unsafe 'operator[]', consider bounds-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-access] // CHECK-FIXES-AT: auto u = BehindDef.at(0); // CHECK-FIXES-FUNC: auto u = f(BehindDef, 0); template int TestTemplate(T t){ return t[0]; - // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:10: warning: possibly unsafe 'operator[]', consider bounds-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-access] } @@ -214,15 +214,15 @@ auto w = TestTemplate<>(p); #define OBJECT_BEHIND_MACRO a auto m1 = SUBSCRIPT_BEHIND_MACRO(0); -// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-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-access] auto m2 = a[ARG_BEHIND_MACRO]; -// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: possibly unsafe 'operator[]', consider bounds-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-access] // 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 bounds-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-access] // CHECK-FIXES-AT: auto m3 = OBJECT_BEHIND_MACRO.at(0); // CHECK-FIXES-FUNC: auto m3 = f(OBJECT_BEHIND_MACRO, 0); @@ -230,22 +230,22 @@ auto m3 = OBJECT_BEHIND_MACRO[0]; std::array longname; auto z1 = longname [ 0 ] ; -// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:22: warning: possibly unsafe 'operator[]', consider bounds-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-access] // 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 bounds-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-access] // 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 bounds-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-access] // 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 +//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-no-excl.cpp -#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h" +#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h" class ExcludedClass1 { public: @@ -269,37 +269,37 @@ class ExcludedClass2 { 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-MESSAGES-DEFAULT-NO-EXCL: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // 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-MESSAGES-DEFAULT-NO-EXCL: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // CHECK-FIXES-AT-NO-EXCL: auto x2 = E2.at(0); // CHECK-FIXES-FUNC-NO-EXCL: auto x2 = f(E2, 0); std::map 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-MESSAGES-DEFAULT-NO-EXCL: :[[@LINE-1]]:23: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // 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 +//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-excl.cpp -#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h" +#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h" std::map 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-MESSAGES-DEFAULT-EXCL: :[[@LINE-1]]:21: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // 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 +//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp #ifdef CXX_23 -#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses.h" +#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h" namespace std { template @@ -316,26 +316,26 @@ namespace std { std::array_cxx_23 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-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // CHECK-FIXES-AT-CXX-23: auto b23 = a.at(); // CHECK-FIXES-FUNC-CXX-23: auto b23 = f(a); // CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto b23 = g(a); -// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] +// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-6]]:{{.*}}: note: FIX-IT applied suggested code changes 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-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // CHECK-FIXES-AT-CXX-23: auto fa23 = (&a)->at(); // CHECK-FIXES-FUNC-CXX-23: auto fa23 = f(*(&a)); // CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fa23 = g(*(&a)); -// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] +// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-6]]:{{.*}}: note: FIX-IT applied suggested code changes 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-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // CHECK-FIXES-AT-CXX-23: auto fd23 = a.at(); // CHECK-FIXES-FUNC-CXX-23: auto fd23 = f(a); // CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fd23 = g(a); -// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-accesses] +// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] // CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-6]]:{{.*}}: note: FIX-IT applied suggested code changes #endif From f8fc4951dc5fac173a2704aeb0c2a47106f14e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 12 Jul 2025 13:56:08 +0200 Subject: [PATCH 094/101] Update clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp Co-authored-by: Baranov Victor --- .../ProBoundsAvoidUncheckedContainerAccess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp index 617e02daedf3c..44d8cd8d3c95f 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp @@ -1,4 +1,4 @@ -//===--- ProBoundsAvoidUncheckedContainerAccesses.cpp - clang-tidy --------===// +//===--- ProBoundsAvoidUncheckedContainerAccess.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. From 57e1cd0d7ef3e2fb6e9ee199c413254f045f68fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Sat, 12 Jul 2025 14:16:22 +0200 Subject: [PATCH 095/101] Fix header comment alignment --- .../ProBoundsAvoidUncheckedContainerAccess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp index 44d8cd8d3c95f..35f432efa88ca 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.cpp @@ -1,4 +1,4 @@ -//===--- ProBoundsAvoidUncheckedContainerAccess.cpp - clang-tidy --------===// +//===--- ProBoundsAvoidUncheckedContainerAccess.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. From bd5fa9718b35e812f8f285f9bba4e5e3040a427f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Mon, 14 Jul 2025 13:17:31 +0200 Subject: [PATCH 096/101] docs: reword paragraph about excluded STL containers --- .../pro-bounds-avoid-unchecked-container-access.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst index f05184e7bc4d6..921b3ddd18ad2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst @@ -25,10 +25,7 @@ and will generate a warning. -STL containers that do not access memory outside the memory allocated by the -container via ``operator[]`` are excluded from this check. Excluded classes, -including the STL containers excluded by default, can be customized via -:option:`ExcludeClasses`. +STL containers for which operator[] is well-defined for all inputs are excluded from this check (e.g.: std::map::operator[]). This check enforces part of the `SL.con.3 ` From a453616b76ede3009e9e41cb6c6ba02613c828b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 15 Jul 2025 10:19:55 +0200 Subject: [PATCH 097/101] Update ProBoundsAvoidUncheckedContainerAccess.h Co-authored-by: EugeneZelenko --- .../cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.h index 9fd0c922ed4c4..cfd52d69c0f58 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccess.h @@ -1,4 +1,4 @@ -//===--- ProBoundsAvoidUncheckedContainerAccess.h - clang-tidy---*- C++ -*-===// +//===--- ProBoundsAvoidUncheckedContainerAccess.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 743b42bae03b68684416bdbbc9f2032da57a98d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Tue, 15 Jul 2025 11:38:54 +0200 Subject: [PATCH 098/101] docs: add missing backticks --- .../pro-bounds-avoid-unchecked-container-access.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst index 921b3ddd18ad2..5f3e584e81669 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst @@ -25,7 +25,8 @@ and will generate a warning. -STL containers for which operator[] is well-defined for all inputs are excluded from this check (e.g.: std::map::operator[]). +STL containers for which operator[] is well-defined for all inputs are excluded +from this check (e.g.: ``std::map::operator[]``). This check enforces part of the `SL.con.3 ` From d6ccbfcd4d465ce2c753ea1ce1362c02a61ec1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <24569379+paulhdk@users.noreply.github.com> Date: Mon, 4 Aug 2025 18:16:59 +0200 Subject: [PATCH 099/101] Update clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst Co-authored-by: EugeneZelenko --- .../pro-bounds-avoid-unchecked-container-access.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst index 5f3e584e81669..a6b5996be1809 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst @@ -54,8 +54,7 @@ Options The function to use in the `function` mode. For C++23 and beyond, the passed function must support the empty subscript operator, i.e., the case where ``a[]`` becomes ``f(a)``. :option:`FixFunctionEmptyArgs` can be - used to override the suggested function in that case. The default for - `FixFunction` is `gsl::at`. + used to override the suggested function in that case. The default is `gsl::at`. .. option:: FixFunctionEmptyArgs From 96309528b1d4f77aa78841f8fff4fdceace02ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= <24569379+paulhdk@users.noreply.github.com> Date: Mon, 4 Aug 2025 20:59:54 +0200 Subject: [PATCH 100/101] Update clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst Co-authored-by: Baranov Victor --- .../pro-bounds-avoid-unchecked-container-access.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-access.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst index a6b5996be1809..3d06a4766cdbc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst @@ -25,7 +25,7 @@ and will generate a warning. -STL containers for which operator[] is well-defined for all inputs are excluded +STL containers for which ``operator[]`` is well-defined for all inputs are excluded from this check (e.g.: ``std::map::operator[]``). This check enforces part of the `SL.con.3 From 83e138fc9e642218d99a6de440f99469e51a81ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Heidekr=C3=BCger?= Date: Fri, 8 Aug 2025 16:01:55 +0200 Subject: [PATCH 101/101] Update clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst Co-authored-by: EugeneZelenko --- .../pro-bounds-avoid-unchecked-container-access.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-access.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst index 3d06a4766cdbc..556d90213b216 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst @@ -61,4 +61,4 @@ Options The function to use in the `function` mode for the empty subscript operator case in C++23 and beyond only. If no fixes should be made for empty subscript operators, pass an empty string. In that case, only the warnings - will be printed. The default is the value of `FixFunction`. + will be printed. The default is the value of :option:`FixFunction`.