[clang-tools-extra] Create a new check to look for mis-use in calls that take iterators (PR #99917)

Julian Schmidt via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 26 11:35:10 PDT 2024


================
@@ -0,0 +1,756 @@
+//===--- IncorrectIteratorsCheck.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 "IncorrectIteratorsCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersMacros.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <functional>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+namespace {
+using SVU = llvm::SmallVector<unsigned, 3>;
+/// Checks to see if a all the parameters of a template function with a given
+/// index refer to the same type.
+AST_MATCHER_P(FunctionDecl, areParametersSameTemplateType, SVU, Indexes) {
+  const FunctionTemplateDecl *TemplateDecl = Node.getPrimaryTemplate();
+  if (!TemplateDecl)
+    return false;
+  const FunctionDecl *FuncDecl = TemplateDecl->getTemplatedDecl();
+  if (!FuncDecl)
+    return false;
+  assert(!Indexes.empty());
+  if (llvm::any_of(Indexes, [Count(FuncDecl->getNumParams())](unsigned Index) {
+        return Index >= Count;
+      }))
+    return false;
+  const ParmVarDecl *FirstParam = FuncDecl->getParamDecl(Indexes.front());
+  if (!FirstParam)
+    return false;
+  QualType Type = FirstParam->getOriginalType();
+  for (auto Item : llvm::drop_begin(Indexes)) {
+    const ParmVarDecl *Param = FuncDecl->getParamDecl(Item);
+    if (!Param)
+      return false;
+    if (Param->getOriginalType() != Type)
+      return false;
+  }
+  return true;
+}
+AST_MATCHER_P(FunctionDecl, isParameterTypeUnique, unsigned, Index) {
+  const FunctionTemplateDecl *TemplateDecl = Node.getPrimaryTemplate();
+  if (!TemplateDecl)
+    return false;
+  const FunctionDecl *FuncDecl = TemplateDecl->getTemplatedDecl();
+  if (!FuncDecl)
+    return false;
+  if (Index >= FuncDecl->getNumParams())
+    return false;
+  const ParmVarDecl *MainParam = FuncDecl->getParamDecl(Index);
+  if (!MainParam)
+    return false;
+  QualType Type = MainParam->getOriginalType();
+  for (unsigned I = 0, E = FuncDecl->getNumParams(); I != E; ++I) {
+    if (I == Index)
+      continue;
+    const ParmVarDecl *Param = FuncDecl->getParamDecl(I);
+    if (!Param)
+      continue;
+    if (Param->getOriginalType() == Type)
+      return false;
+  }
+  return true;
+}
+struct NameMatchers {
+  ArrayRef<StringRef> FreeNames;
+  ArrayRef<StringRef> MethodNames;
+};
+
+struct NamePairs {
+  NameMatchers BeginNames;
+  NameMatchers EndNames;
+};
+
+struct FullState {
+  NamePairs Forward;
+  NamePairs Reversed;
+  NamePairs Combined;
+  NameMatchers All;
+  ArrayRef<StringRef> MakeReverseIterator;
+};
+
+} // namespace
+
+static constexpr char FirstRangeArg[] = "FirstRangeArg";
+static constexpr char FirstRangeArgExpr[] = "FirstRangeArgExpr";
+static constexpr char ReverseBeginBind[] = "ReverseBeginBind";
+static constexpr char ReverseEndBind[] = "ReverseEndBind";
+static constexpr char SecondRangeArg[] = "SecondRangeArg";
+static constexpr char SecondRangeArgExpr[] = "SecondRangeArgExpr";
+static constexpr char ArgMismatchBegin[] = "ArgMismatchBegin";
+static constexpr char ArgMismatchEnd[] = "ArgMismatchEnd";
+static constexpr char ArgMismatchExpr[] = "ArgMismatchExpr";
+static constexpr char ArgMismatchRevBind[] = "ArgMismatchRevBind";
+static constexpr char Callee[] = "Callee";
+static constexpr char Internal[] = "Internal";
+static constexpr char InternalOther[] = "InternalOther";
+static constexpr char InternalArgument[] = "InternalArgument";
+static constexpr char OutputRangeEnd[] = "OutputRangeEnd";
+static constexpr char OutputRangeBegin[] = "OutputRangeBegin";
+
+static auto
+makeExprMatcher(ast_matchers::internal::Matcher<Expr> ArgumentMatcher,
+                const NameMatchers &Names, ArrayRef<StringRef> MakeReverse,
+                const NameMatchers &RevNames, StringRef RevBind) {
+  return expr(anyOf(
+      cxxMemberCallExpr(argumentCountIs(0),
+                        callee(cxxMethodDecl(hasAnyName(Names.MethodNames))),
+                        on(ArgumentMatcher)),
+      callExpr(argumentCountIs(1),
+               hasDeclaration(functionDecl(hasAnyName(Names.FreeNames))),
+               hasArgument(0, ArgumentMatcher)),
+      callExpr(
+          callee(functionDecl(hasAnyName(MakeReverse))), argumentCountIs(1),
----------------
5chmidti wrote:

It would be better to check the argument count before matching the name

https://github.com/llvm/llvm-project/pull/99917


More information about the cfe-commits mailing list