Index: clang-tidy/misc/CMakeLists.txt =================================================================== --- clang-tidy/misc/CMakeLists.txt +++ clang-tidy/misc/CMakeLists.txt @@ -14,6 +14,7 @@ NewDeleteOverloadsCheck.cpp NoexceptMoveConstructorCheck.cpp NonCopyableObjects.cpp + PointerArithmeticCheck.cpp SizeofContainerCheck.cpp StaticAssertCheck.cpp SwappedArgumentsCheck.cpp Index: clang-tidy/misc/MiscTidyModule.cpp =================================================================== --- clang-tidy/misc/MiscTidyModule.cpp +++ clang-tidy/misc/MiscTidyModule.cpp @@ -22,6 +22,7 @@ #include "NewDeleteOverloadsCheck.h" #include "NoexceptMoveConstructorCheck.h" #include "NonCopyableObjects.h" +#include "PointerArithmeticCheck.h" #include "SizeofContainerCheck.h" #include "StaticAssertCheck.h" #include "SwappedArgumentsCheck.h" @@ -61,6 +62,8 @@ "misc-noexcept-move-constructor"); CheckFactories.registerCheck( "misc-non-copyable-objects"); + CheckFactories.registerCheck( + "misc-pointer-arithmetic"); CheckFactories.registerCheck("misc-sizeof-container"); CheckFactories.registerCheck( "misc-static-assert"); Index: clang-tidy/misc/PointerArithmeticCheck.h =================================================================== --- /dev/null +++ clang-tidy/misc/PointerArithmeticCheck.h @@ -0,0 +1,34 @@ +//===--- PointerArithmeticCheck.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_MISC_POINTER_ARITHMETIC_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_POINTER_ARITHMETIC_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { + +/// Flags all kinds of pointer arithmetic +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/misc-pointer-arithmetic.html +class PointerArithmeticCheck : public ClangTidyCheck { +public: + PointerArithmeticCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_POINTER_ARITHMETIC_H + Index: clang-tidy/misc/PointerArithmeticCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/misc/PointerArithmeticCheck.cpp @@ -0,0 +1,41 @@ +//===--- PointerArithmeticCheck.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 "PointerArithmeticCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { + +void PointerArithmeticCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + // We exclude the case where one subtracts two pointers, because that cannot yield an invalid pointer + Finder->addMatcher(binaryOperator(anyOf(hasOperatorName("+"), + hasOperatorName("-"), + hasOperatorName("+="), + hasOperatorName("-=")), + hasEitherOperand(hasType(pointerType())), + hasEitherOperand(hasType(isInteger())) + ).bind("binOp"), this); +} + +void PointerArithmeticCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedOp = Result.Nodes.getNodeAs("binOp"); + + diag(MatchedOp->getExprLoc(), "do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1)"); +} + +} // namespace tidy +} // namespace clang + Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -33,6 +33,7 @@ misc-new-delete-overloads misc-noexcept-move-constructor misc-non-copyable-objects + misc-pointer-arithmetic misc-sizeof-container misc-static-assert misc-swapped-arguments Index: docs/clang-tidy/checks/misc-pointer-arithmetic.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/misc-pointer-arithmetic.rst @@ -0,0 +1,10 @@ +misc-pointer-arithmetic +======================= + +This check flags all usage of pointer arithmetic, because it could lead to an invalid pointer. +Subtraction of two pointers is not flagged by this check. + +Pointers should only refer to single objects, and pointer arithmetic is fragile and easy to get wrong. array_view is a bounds-checked, safe type for accessing arrays of data. + +This rule is part of the "Bounds safety" profile of the C++ Core Guidelines, see +https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#-bounds1-dont-use-pointer-arithmetic-use-array_view-instead \ No newline at end of file Index: test/clang-tidy/misc-pointer-arithmetic.cpp =================================================================== --- /dev/null +++ test/clang-tidy/misc-pointer-arithmetic.cpp @@ -0,0 +1,28 @@ +// RUN: %python %S/check_clang_tidy.py %s misc-pointer-arithmetic %t + + +enum E { + ENUM_LITERAL = 1 +}; + +void f() { + int i = 4; + int j = i + 1; //OK, integral arithmetic + int* p = 0; + int* q = p + 4; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [misc-pointer-arithmetic] + p += 4; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [misc-pointer-arithmetic] + q -= 1; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [misc-pointer-arithmetic] + q = p - 1; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [misc-pointer-arithmetic] + i += p; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [misc-pointer-arithmetic] + p = q - ENUM_LITERAL; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [misc-pointer-arithmetic] + p = q + ENUM_LITERAL; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [misc-pointer-arithmetic] + + int a = p - q; //OK, result is arithmetic +} \ No newline at end of file