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

2024-06-12 Thread Paul Heidekrüger via cfe-commits

PBHDK wrote:

> Yes, you can just submit new PR, reference this one.

Done! Here it is: https://github.com/llvm/llvm-project/pull/95220

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-11 Thread Carlos Galvez via cfe-commits

carlosgalvezp wrote:

> I don't think it is a good solution.

Can you elaborate?

As I wrote above, the C++ Core Guidelines do not require using `at()`. 
Therefore the check would be doing something different than what the guidelines 
require. The reason they don't require it is that there's multiple solutions to 
this problem, and using `at()` can even do more harm than good.

Warning about operator[] is good; but the fix is not globally accepted best 
practice (as per comments above). All I'm saying is that if this fix is wanted, 
it should be opt-in, which should be fairly easy to achieve?

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-11 Thread Congcong Cai via cfe-commits

HerrCai0907 wrote:

> To be clear and reiterate my previous comment: this check should NOT require 
> users to use at(). That behavior should be opt-in. It should only warn about 
> using operator[]. It's up to the users to figure out what the best 
> replacement is.

I don't think it is a good solution. For this kind of projects, they should 
disable this check directly.

Maybe it is optimization to disable this check if exception feature is disabled.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-10 Thread Carlos Galvez via cfe-commits

carlosgalvezp wrote:

To be clear and reiterate my previous comment: this check should NOT require 
users to use at(). That behavior should be opt-in. It should only warn about 
using operator[]. It's up to the users to figure out what the best replacement 
is.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-10 Thread Congcong Cai via cfe-commits

https://github.com/HerrCai0907 requested changes to this pull request.

`at` and `operator[]` in `std::map` have different meanings. `operator[]` will 
insert value if key does not exist but `at` won't. Please limit this check only 
for index containers instead of key-value containers.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-10 Thread Piotr Zegar via cfe-commits

PiotrZSL wrote:

Yes, you can just submit new PR, reference this one.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-10 Thread Paul Heidekrüger via cfe-commits

PBHDK wrote:

> Check if you can commit to sebwolf-de:avoid-bounds-error-check

Unfortunately, we can't. We do not have access to Sebastian's LLVM fork.
Since Sebastian is out of office right now - this is one of the reasons we're 
involved - would you be ok with us submitting a new PR with our changes where 
we reference the current PR?



https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-07 Thread Piotr Zegar via cfe-commits

PiotrZSL wrote:

Check if you can commit to sebwolf-de:avoid-bounds-error-check

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-07 Thread Paul Heidekrüger via cfe-commits

PBHDK wrote:

> > > I am adding @leunam99 and @PBHDK to the PR, who will contribute in the 
> > > next few weeks.
> > 
> > 
> > Since we cannot push to this PR, we will be submitting a new PR with 
> > @sebwolf-de's + our work, correct, @EugeneZelenko, @PiotrZSL, @HerrCai0907?
> 
> Could you please resolve conversations for fixed comments?

Once we're clear on all our questions (see comments above), we'll submit a new 
PR that'll resolve all comments.
The code is ready, but we don't want to submit the PR as long as we still have 
open questions.
The problem is that we can't mark them as resolved on GitHub ourselves, and 
Sebastian is out-of-office right now.

I don't know if you can assign us to this PR somehow, but if not, someone else 
would have to mark them as resolved.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-03 Thread via cfe-commits

EugeneZelenko wrote:

> > I am adding @leunam99 and @PBHDK to the PR, who will contribute in the next 
> > few weeks.
> 
> Since we cannot push to this PR, we will be submitting a new PR with 
> @sebwolf-de's + our work, correct, @EugeneZelenko, @PiotrZSL, @HerrCai0907?

Could you please resolve conversations for fixed comments?

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-03 Thread Manuel Pietsch via cfe-commits


@@ -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;

leunam99 wrote:

As suggested, we added a test where the object is a template parameter and the 
method is called once with a class that has `at()` and once with a class that 
has not, but we are not sure what the best behaviour is. Should we 

-  not warn, because the fix suggested in the message will lead the other 
instantiation to not compile?
- warn at the place that requires the template instantiation?
- keep the warning and add the name of the class of the object / the template 
parameters that lead to the message?

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-03 Thread Manuel Pietsch via cfe-commits


@@ -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;

leunam99 wrote:

We had a look at the standard library; the same applies to `std::unordered_map` 
and `std::flat_map` too, correct? So, by default, we'd be excluding `std::map`, 
`std::unordered_map`, and `std::flat_map`. Can you think of any others?

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-06-03 Thread Paul Heidekrüger via cfe-commits

PBHDK wrote:

> I am adding @leunam99 and @PBHDK to the PR, who will contribute in the next 
> few weeks.

Since we cannot push to this PR, we will be submitting a new PR with 
@sebwolf-de's + our work, correct, @EugeneZelenko, @PiotrZSL, @HerrCai0907?

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-05-24 Thread Sebastian Wolf via cfe-commits

https://github.com/sebwolf-de updated 
https://github.com/llvm/llvm-project/pull/90043

>From 8eb5863305e8f9a1311a540faf35f24fc6f55c6c Mon Sep 17 00:00:00 2001
From: Sebastian Wolf 
Date: Wed, 17 Apr 2024 16:16:35 +0200
Subject: [PATCH 1/3] 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 0..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 0..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

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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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");

PiotrZSL wrote:

use more proper names than x/f

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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;

PiotrZSL wrote:

add tests with:
- std::map,
- where operator[] is behind macro
- where argument to operator is behind macro
- where object is behind macro
- where class derive from std::map/array
- where std::array is behind typedef
- where object is an template parameter, and method is called once with class 
that has .at and once with class that has not
- ...


https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -57,6 +58,8 @@ namespace cppcoreguidelines {
 class CppCoreGuidelinesModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+CheckFactories.registerCheck(
+"cppcoreguidelines-avoid-bounds-errors");

PiotrZSL wrote:

check name cppcoreguidelines-avoid-bounds-errors is too generic for what check 
is doing, name it something like 
cppcoreguidelines-prefer-at-over-subscript-operator, or something simillar. 
Figure something out.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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.")

PiotrZSL wrote:

keep diagnostic an lower case, not need for point at the end

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,20 @@
+.. title:: clang-tidy - cppcoreguidelines-avoid-bounds-errors
+
+cppcoreguidelines-avoid-bounds-errors
+=
+
+This check enforces the `SL.con.3 
`
 guideline.

PiotrZSL wrote:

in first line put short description what actually check does, and synchronize 
it with release notes and doxygen documentation for a class

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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);

PiotrZSL wrote:

you could verify at this level that exceptions are enabled (check LangOptions).
Because fix may not be perfect, you may consider attaching fix to note instead 
of warning.
And raise also a note that would point where operator[] is defined, and where 
method at is.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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")))

PiotrZSL wrote:

instead of hasName use hasOverloadedOperatorName.
and instead of callExpr use cxxOperatorCallExpr, and verify on this level that 
object got also .at method.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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;

PiotrZSL wrote:

check may break std::map currently.
for example:
```
   someMap[key] = 10; -> someMap.at(key) = 10;
```

This would change behavior of code.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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;
+  }

PiotrZSL wrote:

Nope, instead verify that callee got an `.at` method that take same arguments, 
got same `const/rref` qualifier. 
In such case this will work for all containers that support this notation, not 
only those,

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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, ")");

PiotrZSL wrote:

Do not operate at strings, operate by using tokens/source location, because 
otherwise, single space will break code.


https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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);

PiotrZSL wrote:

consider adding option to specify excluded classes, if class detection will be 
automatic.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL edited 
https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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;
+};

PiotrZSL wrote:

ignore implicit code with TK_IgnoreUnlessSpelledInSource.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits


@@ -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);

PiotrZSL wrote:

may not work with macros.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL requested changes to this pull request.

Idea is fine, implementation is lacking critical parts.
Please check comments, fix them.
If you will have some questions, just ask.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread via cfe-commits

cor3ntin wrote:

> Please note: the guidelines do not require one to replace [] with at(), 
> that's just one of the possible solutions. Actually at() is banned in many 
> codebases where exceptions are banned.
> 
> It would be good to make this fix-it opt-in, configurable via option, so the 
> check only emits a warning by default.

+1 
I find the fixit rather concerning, as it does not correspond to any widely 
accepted good practice. 
Using `at` does not fixes any issue, it just "shifts right" the detection of a 
problem.

The advices  this is trying to get at is:
 * assert in the operator[] (or use another precondition mechanism
 * Use ASan
 * use algorithms instead of loops and direct element manipulation wherever 
possible.


https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Carlos Galvez via cfe-commits

carlosgalvezp wrote:

Please note: the guidelines do not require one to replace [] with at(), that's 
just one of the possible solutions. Actually at() is banned in many codebases 
where exceptions are banned.

It would be good to make this fix-it opt-in,  configurable via option, so the 
check only emits a warning by default.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread via cfe-commits


@@ -0,0 +1,20 @@
+.. title:: clang-tidy - cppcoreguidelines-avoid-bounds-errors
+
+cppcoreguidelines-avoid-bounds-errors
+=
+
+This check enforces the `SL.con.3 
`
 guideline.

EugeneZelenko wrote:

This usually placed at the end of documentation.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread via cfe-commits


@@ -131,6 +131,11 @@ New checks
   to reading out-of-bounds data due to inadequate or incorrect string null
   termination.
 
+- New :doc:`cppcoreguidelines-avoid-bounds-errors
+  ` check.
+
+  Flags the unsafe `operator[]` and replaces it with `at()`.

EugeneZelenko wrote:

Please use double back-ticks for language constructs. Same in documentation.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread via cfe-commits


@@ -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) {

EugeneZelenko wrote:

`static`?

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread via cfe-commits


@@ -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;
+};

EugeneZelenko wrote:

Please add `isLanguageVersionSupported`.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread via cfe-commits


@@ -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;

EugeneZelenko wrote:

Please separate with newline.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread via cfe-commits


@@ -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"
+

EugeneZelenko wrote:

Excessive newline.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread via cfe-commits


@@ -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();

EugeneZelenko wrote:

Please do not use `auto` - type is not spelled explicitly.

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-tidy

Author: Sebastian Wolf (sebwolf-de)


Changes

The string based test to find out whether the check is applicable on the class 
is not ideal, but I did not find a more elegant way, yet. If there is more 
clang-query magic available, that I'm not aware of, I'm happy to adapt that.

---
Full diff: https://github.com/llvm/llvm-project/pull/90043.diff


8 Files Affected:

- (added) 
clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp (+81) 
- (added) 
clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h (+32) 
- (modified) clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt (+1) 
- (modified) 
clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp 
(+3) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5) 
- (added) 
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
 (+20) 
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1) 
- (added) 
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp
 (+66) 


``diff
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 00..524c21b5bdb818
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
@@ -0,0 +1,81 @@
+//===--- AvoidBoundsErrorsCheck.cpp - clang-tidy 
--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AvoidBoundsErrorsCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+#include 
+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 00..f915729cd7bbee
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
@@ -0,0 +1,32 @@
+//===--- AvoidBoundsErrorsCheck.h - clang-tidy --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDBOUNDSERRORSCHECK_H
+#define 
LLVM_CL

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

2024-04-25 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-tools-extra

Author: Sebastian Wolf (sebwolf-de)


Changes

The string based test to find out whether the check is applicable on the class 
is not ideal, but I did not find a more elegant way, yet. If there is more 
clang-query magic available, that I'm not aware of, I'm happy to adapt that.

---
Full diff: https://github.com/llvm/llvm-project/pull/90043.diff


8 Files Affected:

- (added) 
clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp (+81) 
- (added) 
clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h (+32) 
- (modified) clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt (+1) 
- (modified) 
clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp 
(+3) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5) 
- (added) 
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-bounds-errors.rst
 (+20) 
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1) 
- (added) 
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-bounds-errors.cpp
 (+66) 


``diff
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 00..524c21b5bdb818
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
@@ -0,0 +1,81 @@
+//===--- AvoidBoundsErrorsCheck.cpp - clang-tidy 
--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AvoidBoundsErrorsCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+#include 
+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 00..f915729cd7bbee
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
@@ -0,0 +1,32 @@
+//===--- AvoidBoundsErrorsCheck.h - clang-tidy --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDBOUNDSERRORSCHECK_H
+#define 

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

2024-04-25 Thread via cfe-commits

github-actions[bot] wrote:



Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this 
page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using `@` followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from 
other developers.

If you have further questions, they may be answered by the [LLVM GitHub User 
Guide](https://llvm.org/docs/GitHub.html).

You can also ask questions in a comment on this PR, on the [LLVM 
Discord](https://discord.com/invite/xS7Z362) or on the 
[forums](https://discourse.llvm.org/).

https://github.com/llvm/llvm-project/pull/90043
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2024-04-25 Thread Sebastian Wolf via cfe-commits

https://github.com/sebwolf-de created 
https://github.com/llvm/llvm-project/pull/90043

The string based test to find out whether the check is applicable on the class 
is not ideal, but I did not find a more elegant way, yet. If there is more 
clang-query magic available, that I'm not aware of, I'm happy to adapt that.

>From 8eb5863305e8f9a1311a540faf35f24fc6f55c6c Mon Sep 17 00:00:00 2001
From: Sebastian Wolf 
Date: Wed, 17 Apr 2024 16:16:35 +0200
Subject: [PATCH] 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 00..524c21b5bdb818
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.cpp
@@ -0,0 +1,81 @@
+//===--- AvoidBoundsErrorsCheck.cpp - clang-tidy 
--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AvoidBoundsErrorsCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+#include 
+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 00..f915729cd7bbee
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidBoundsErrorsCheck.h
@@ -0,0 +1,32 @@
+//===--- AvoidBoundsErrorsCheck.h - clang-tidy --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LL