Prazek updated this revision to Diff 81606.
Prazek added a comment.
- Small fixes
https://reviews.llvm.org/D27806
Files:
clang-tidy/obvious/CMakeLists.txt
clang-tidy/obvious/InvalidRangeCheck.cpp
clang-tidy/obvious/InvalidRangeCheck.h
clang-tidy/obvious/ObviousTidyModule.cpp
docs/ReleaseNotes.rst
docs/clang-tidy/checks/list.rst
docs/clang-tidy/checks/obvious-invalid-range.rst
test/clang-tidy/obvious-invalid-range.cpp
Index: test/clang-tidy/obvious-invalid-range.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/obvious-invalid-range.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s obvious-invalid-range %t
+
+namespace std {
+
+template <class InputIterator, class OutputIterator>
+OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) {
+ return result;
+}
+
+template <class InputIterator, class OutputIterator>
+OutputIterator move(InputIterator first, InputIterator last, OutputIterator result) {
+ return result;
+}
+
+template <typename T>
+T move(T &&) { return T(); }
+
+template <class InputIterator, typename Val>
+void fill(InputIterator first, InputIterator last, const Val &v) {
+}
+
+template <typename T>
+class vector {
+public:
+ T *begin();
+ T *end();
+};
+}
+
+void test_copy() {
+ std::vector<int> v, v2;
+ std::copy(v.begin(), v2.end(), v2.begin());
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [obvious-invalid-range]
+
+ std::copy(v.begin(), v.end(), v2.begin());
+}
+
+void test_move() {
+ std::vector<int> v;
+ auto &v2 = v;
+ std::move(v.begin(), v2.end(), v2.begin());
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects
+
+ std::move(v.begin(), v.end(), v2.begin());
+ std::move(v.begin());
+ test_copy();
+}
Index: docs/clang-tidy/checks/obvious-invalid-range.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/obvious-invalid-range.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - obvious-invalid-range
+
+obvious-invalid-range
+=====================
+
+This check finds invalid calls to algorithms with obviously invalid range of
+iterators like:
+
+.. code-block:: c++
+ std::fill(v.begin(), v2.end(), it);
+
+It checks if first and second argument of call is call to ``begin()``
+and ``end()``, but on different objects (having different name).
+
+By default it looks for all algorithms from ``<algorithm>``. This can be
+changed by using ``AlgorithmNames`` option, where empty list means that any
+function name will be accepted.
\ No newline at end of file
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -65,6 +65,7 @@
misc-inaccurate-erase
misc-incorrect-roundings
misc-inefficient-algorithm
+ misc-invalid-range
misc-macro-parentheses
misc-macro-repeated-side-effects
misc-misplaced-const
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -114,6 +114,15 @@
Flags MPI function calls with a buffer type and MPI data type mismatch.
+- New obvious module with checks for obvious bugs that probably won't be found
+ in working code, but can be found while looking for an obvious bug in broken
+ code.
+- New `obvious-invalid-range
+ <http://clang.llvm.org/extra/clang-tidy/checks/misc-invalid-range.html>`_ check
+
+ Warns if algorithm is used with ``.begin()`` and ``.end()`` from different
+ variables.
+
- New `performance-inefficient-string-concatenation
<http://clang.llvm.org/extra/clang-tidy/checks/performance-inefficient-string-concatenation.html>`_ check
Index: clang-tidy/obvious/ObviousTidyModule.cpp
===================================================================
--- clang-tidy/obvious/ObviousTidyModule.cpp
+++ clang-tidy/obvious/ObviousTidyModule.cpp
@@ -11,6 +11,7 @@
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
+#include "InvalidRangeCheck.h"
using namespace clang::ast_matchers;
namespace clang {
@@ -20,7 +21,7 @@
class ObviousModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
- // Add obvious checks here.
+ CheckFactories.registerCheck<InvalidRangeCheck>("obvious-invalid-range");
}
};
Index: clang-tidy/obvious/InvalidRangeCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/obvious/InvalidRangeCheck.h
@@ -0,0 +1,40 @@
+//===--- InvalidRangeCheck.h - clang-tidy------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RANGE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RANGE_H
+
+#include "../ClangTidy.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace obvious {
+
+/// Find invalid call to algorithm with obviously invalid range of iterators.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-invalid-range.html
+class InvalidRangeCheck : public ClangTidyCheck {
+public:
+ InvalidRangeCheck(StringRef Name, ClangTidyContext *Context);
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+ std::vector<std::string> AlgorithmNames;
+};
+
+} // namespace obvious
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RANGE_H
Index: clang-tidy/obvious/InvalidRangeCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/obvious/InvalidRangeCheck.cpp
@@ -0,0 +1,97 @@
+//===--- InvalidRangeCheck.cpp - clang-tidy--------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InvalidRangeCheck.h"
+#include "../utils/OptionsUtils.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace obvious {
+
+const std::string CXX_AlgorithmNames =
+ "std::for_each; std::find; std::find_if; std::find_end; "
+ "std::find_first_of; std::adjacent_find; std::count; std::count_if;"
+ "std::mismatch; std::equal; std::search; std::copy; "
+ "std::copy_backward; std::swap_ranges; std::transform; std::replace"
+ "std::replace_if; std::replace_copy; std::replace_copy_if; std::fill; "
+ "std::fill_n; std::generate; std::generate_n; std::remove; std::remove_if"
+ "std::remove_copy; std::remove_copy_if; std::unique; std::unique_copy;"
+ "std::reverse; std::reverse_copy; std::rotate; std::rotate_copy; "
+ "std::random_shuffle; std::partition; std::stable_partition; std::sort;"
+ "std::stable_sort; std::partial_sort; std::partial_sort_copy; "
+ "std::nth_element; std::lower_bound; std::upper_bound; std::equal_range;"
+ "std::binary_search; std::merge; std::inplace_merge; std::includes; "
+ "std::set_union; std::set_intersection; std::set_difference; "
+ "std::set_symetric_difference; std::push_heap; std::pop_heap"
+ "std::make_heap; std::sort_heap; std::min; std::max; std::min_element; "
+ "std::max_element; std::lexicographical_compare; std::next_permutation; "
+ "std::prev_permutation";
+
+const auto CXX11_AlgorithmNames =
+ CXX_AlgorithmNames + "; "
+ "std::all_of; std::any_of; std::none_of; std::find_if_not; "
+ "std::is_permutation; std::copy_n; std::copy_if; std::move; "
+ "std::move_backward; std::shuffle; std::is_partitioned;"
+ "std::partition_copy; std::partition_point; std::is_sorted"
+ "std::is_sorted_until; std::is_heap; std::is_heap_until; std::minmax; "
+ "std::minmax_element";
+
+InvalidRangeCheck::InvalidRangeCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ AlgorithmNames(utils::options::parseStringList(Options.get(
+ "AlgorithmNames", getLangOpts().CPlusPlus11 ? CXX11_AlgorithmNames
+ : CXX_AlgorithmNames))) {}
+
+void InvalidRangeCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ // Not so small vector. 80 because there are about that many algorithms.
+ const auto Names =
+ SmallVector<StringRef, 80>(AlgorithmNames.begin(), AlgorithmNames.end());
+
+ auto CallsAlgorithm = hasDeclaration(
+ functionDecl(Names.size() > 0 ? hasAnyName(Names) : anything()));
+
+ auto MemberCallWithName = [](StringRef MethodName, StringRef BindThisName) {
+ return cxxMemberCallExpr(
+ hasDeclaration(cxxMethodDecl(hasName(MethodName))),
+ onImplicitObjectArgument(declRefExpr().bind(BindThisName)));
+ };
+ // FIXME: match for std::begin(arg) and std::end(arg2)
+ // FIXME: some algorithms like std::list::splice(It, list, It, It) take
+ // range as 3rd and 4th argument.
+ Finder->addMatcher(
+ callExpr(hasArgument(0, MemberCallWithName("begin", "first_arg")),
+ hasArgument(1, MemberCallWithName("end", "second_arg")),
+ CallsAlgorithm),
+ this);
+}
+
+void InvalidRangeCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *FirstArg = Result.Nodes.getNodeAs<DeclRefExpr>("first_arg");
+ const auto *SecondArg = Result.Nodes.getNodeAs<DeclRefExpr>("second_arg");
+ if (FirstArg->getNameInfo().getAsString() ==
+ SecondArg->getNameInfo().getAsString())
+ return;
+
+ diag(FirstArg->getExprLoc(),
+ "call to algorithm with begin and end from different objects");
+}
+
+void InvalidRangeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "AlgorithmNames",
+ utils::options::serializeStringList(AlgorithmNames));
+}
+
+} // namespace obvious
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/obvious/CMakeLists.txt
===================================================================
--- clang-tidy/obvious/CMakeLists.txt
+++ clang-tidy/obvious/CMakeLists.txt
@@ -2,6 +2,7 @@
add_clang_library(clangTidyObviousModule
ObviousTidyModule.cpp
+ InvalidRangeCheck.cpp
LINK_LIBS
clangAST
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits