Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "InaccurateEraseCheck.h"
#include "IncDecInConditionsCheck.h"
#include "IncorrectEnableIfCheck.h"
#include "IncorrectIteratorsCheck.h"
#include "IncorrectRoundingsCheck.h"
#include "InfiniteLoopCheck.h"
#include "IntegerDivisionCheck.h"
Expand Down Expand Up @@ -139,6 +140,8 @@ class BugproneModule : public ClangTidyModule {
"bugprone-inaccurate-erase");
CheckFactories.registerCheck<IncorrectEnableIfCheck>(
"bugprone-incorrect-enable-if");
CheckFactories.registerCheck<IncorrectIteratorsCheck>(
"bugprone-incorrect-iterators");
CheckFactories.registerCheck<ReturnConstRefFromParameterCheck>(
"bugprone-return-const-ref-from-parameter");
CheckFactories.registerCheck<SwitchMissingDefaultCaseCheck>(
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule
ImplicitWideningOfMultiplicationResultCheck.cpp
InaccurateEraseCheck.cpp
IncorrectEnableIfCheck.cpp
IncorrectIteratorsCheck.cpp
ReturnConstRefFromParameterCheck.cpp
SuspiciousStringviewDataUsageCheck.cpp
SwitchMissingDefaultCaseCheck.cpp
Expand Down
1,214 changes: 1,214 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/IncorrectIteratorsCheck.cpp

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/IncorrectIteratorsCheck.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//===--- IncorrectIteratorsCheck.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_BUGPRONE_INCORRECTITERATORSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INCORRECTITERATORSCHECK_H

#include "../ClangTidyCheck.h"
#include "llvm/ADT/StringRef.h"

namespace clang::tidy::bugprone {

/// Detects calls to iterator algorithms that are called with potentially
/// invalid arguments.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/incorrect-iterators.html
class IncorrectIteratorsCheck : public ClangTidyCheck {
public:
IncorrectIteratorsCheck(StringRef Name, ClangTidyContext *Context);
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void storeOptions(ClangTidyOptions::OptionMap &Options) override;
std::optional<TraversalKind> getCheckTraversalKind() const override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;

private:
std::vector<StringRef> BeginFree;
std::vector<StringRef> EndFree;
std::vector<StringRef> BeginMethod;
std::vector<StringRef> EndMethod;
std::vector<StringRef> RBeginFree;
std::vector<StringRef> REndFree;
std::vector<StringRef> RBeginMethod;
std::vector<StringRef> REndMethod;
std::vector<StringRef> MakeReverseIterator;
Comment on lines +32 to +40
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are usually const, as these correspond to the options obtained from the user's configuration.

};

} // namespace clang::tidy::bugprone

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INCORRECTITERATORSCHECK_H
6 changes: 6 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^

- New :doc:`bugprone-incorrect-iterators
<clang-tidy/checks/bugprone/incorrect-iterators>` check.

Detects calls to iterator algorithms that are called with potentially
invalid arguments.

New check aliases
^^^^^^^^^^^^^^^^^

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
.. title:: clang-tidy - bugprone-incorrect-iterators

bugprone-incorrect-iterators
============================

Detects calls to iterator algorithms where they are called with potentially
invalid arguments.

Different ranges
================

Looks for calls where the range for the ``begin`` argument is different to the
``end`` argument.

.. code-block:: c++

std::find(a.begin(), b.end(), 0);
std::find(std::begin(a), std::end(b));

Mismatched Begin/End
====================

Looks for calls where the ``begin`` parameter is passed as an ``end`` argument or
vice versa.

.. code-block:: c++

std::find(a.begin(), a.begin(), 0); // Second argument should be a.end().
std::find(a.end(), a.end(), 0); // First argument should be a.begin().

3 argument ranges
=================

Looks for calls which accept a range defined by [first, middle, last] and
ensures correct arguments are supplied.

.. code-block:: c++

std::rotate(a.begin(), a.end(), pivot); // a.end() likely should be 3rd argument.
std::rotate(a.bgein(), pivot(), b.end()) // different range past to begin/end.

Container Methods
=================

Looks for calls to methods on containers that expect an iterator inside the
container but are given a different container.

.. code-block:: c++

vec.insert(other.begin(), 5); // The iterator is invalid for this container.
std::vector<int> Vec{a.begin(), a.begin()}; // Second argument should be a.end().
vec.assign(a.begin(), a.begin()) // Second argument should be a.end().

Output Iterators
================

Looks for calls which accept a single output iterator but are passed the end of
a container.

.. code-block:: c++

std::copy(correct.begin(), correct.end(), incorrect.end());

Iterator Advancing
==================

Looks for calls that advance an iterator outside its range.

.. code-block:: c++

auto Iter = std::next(Cont.end());

Reverse Iteration
=================

The check understands ``rbegin`` and ``rend`` and ensures they are in the
correct places.

.. code-block:: c++

std::find(a.rbegin(), a.rend(), 0); // OK.
std::find(a.rend(), a.rbegin(), 0); // Arguments are swapped.

Manually creating a reverse iterator using the ``std::make_reverse_iterator`` is
also supported, In this case the check looks for calls to ``end`` for the
``begin`` parameter and vice versa. The name of functions for creating reverse
iterator can be configured with the option :option:`MakeReverseIterator`.

.. code-block:: c++

std::find(std::make_reverse_iterator(a.begin()),
std::make_reverse_iterator(a.end()), 0); // Arguments are swapped.
std::find(std::make_reverse_iterator(a.end()),
std::make_reverse_iterator(a.begin()), 0); // OK.
// Understands this spaghetti looking code is actually doing the correct thing.
std::find(a.rbegin(), std::make_reverse_iterator(a.begin()), 0);

Options
-------

.. option:: BeginFree

A semi-colon seperated list of free function names that return an iterator to
the start of a range. Default value is `::std::begin;std::cbegin`.

.. option:: EndFree

A semi-colon seperated list of free function names that return an iterator to
the end of a range. Default value is `::std::end;std::cend`.

.. option:: BeginMethod

A semi-colon seperated list of method names that return an iterator to
the start of a range. Default value is `begin;cbegin`.

.. option:: EndMethod

A semi-colon seperated list of method names that return an iterator to
the end of a range. Default value is `end;cend`.

.. option:: RBeginFree

A semi-colon seperated list of free function names that return a reverse
iterator to the start of a range. Default value is `::std::rbegin;std::crbegin`.

.. option:: REndFree

A semi-colon seperated list of free function names that return a reverse
iterator to the end of a range. Default value is `::std::rend;std::crend`.

.. option:: RBeginMethod

A semi-colon seperated list of method names that return a reverse
iterator to the start of a range. Default value is `rbegin;crbegin`.

.. option:: REndMethod

A semi-colon seperated list of method names that return a reverse
iterator to the end of a range. Default value is `rend;crend`.

.. option:: MakeReverseIterator

A semi-colon seperated list of free functions that convert an interator into a
reverse iterator. Default value is `::std::make_reverse_iterator`.
1 change: 1 addition & 0 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ Clang-Tidy Checks
:doc:`bugprone-inaccurate-erase <bugprone/inaccurate-erase>`, "Yes"
:doc:`bugprone-inc-dec-in-conditions <bugprone/inc-dec-in-conditions>`,
:doc:`bugprone-incorrect-enable-if <bugprone/incorrect-enable-if>`, "Yes"
:doc:`bugprone-incorrect-iterators <bugprone/incorrect-iterators>`,
:doc:`bugprone-incorrect-roundings <bugprone/incorrect-roundings>`,
:doc:`bugprone-infinite-loop <bugprone/infinite-loop>`,
:doc:`bugprone-integer-division <bugprone/integer-division>`,
Expand Down
Loading