Index: clang-tidy/cppcoreguidelines/CMakeLists.txt =================================================================== --- clang-tidy/cppcoreguidelines/CMakeLists.txt +++ clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -2,6 +2,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule CppCoreGuidelinesTidyModule.cpp + ProBoundsPointerArithmeticCheck.cpp ProTypeReinterpretCastCheck.cpp LINK_LIBS Index: clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp =================================================================== --- clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -10,6 +10,7 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "ProBoundsPointerArithmeticCheck.h" #include "ProTypeReinterpretCastCheck.h" namespace clang { @@ -19,6 +20,8 @@ class CppCoreGuidelinesModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "cppcoreguidelines-pro-bounds-pointer-arithmetic"); CheckFactories.registerCheck( "cppcoreguidelines-pro-type-reinterpret-cast"); } Index: clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h @@ -0,0 +1,34 @@ +//===--- ProBoundsPointerArithmeticCheck.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_CPPCOREGUIDELINES_PRO_BOUNDS_POINTER_ARITHMETIC_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_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/cppcoreguidelines-pro-bounds-pointer-arithmetic.html +class ProBoundsPointerArithmeticCheck : public ClangTidyCheck { +public: + ProBoundsPointerArithmeticCheck(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_CPPCOREGUIDELINES_PRO_BOUNDS_POINTER_ARITHMETIC_H + Index: clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp @@ -0,0 +1,52 @@ +//===--- ProBoundsPointerArithmeticCheck.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 "ProBoundsPointerArithmeticCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { + +void ProBoundsPointerArithmeticCheck::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("expr"), + this); + + Finder->addMatcher( + unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), + hasUnaryOperand(hasType(pointerType()))).bind("expr"), + this); + + Finder->addMatcher( + arraySubscriptExpr(hasBase(implicitCastExpr(hasSourceExpression( + hasType(pointerType()))))).bind("expr"), + this); +} + +void +ProBoundsPointerArithmeticCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedExpr = Result.Nodes.getNodeAs("expr"); + + diag(MatchedExpr->getExprLoc(), + "do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1)"); +} + +} // namespace tidy +} // namespace clang Index: docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.rst @@ -0,0 +1,10 @@ +cppcoreguidelines-pro-bounds-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 Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -2,6 +2,7 @@ ========================= .. toctree:: + cppcoreguidelines-pro-bounds-pointer-arithmetic cppcoreguidelines-pro-type-reinterpret-cast google-build-explicit-make-pair google-build-namespaces Index: test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp =================================================================== --- /dev/null +++ test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp @@ -0,0 +1,52 @@ +// RUN: %python %S/check_clang_tidy.py %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t + + +enum E { + ENUM_LITERAL = 1 +}; + +int i = 4; +int j = 1; +int* p = 0; +int* q = 0; + +void fail() { + q = p + 4; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + q = p - 1; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p += 4; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + q -= 1; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p = q - ENUM_LITERAL; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p = q + ENUM_LITERAL; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p++; + // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + ++p; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p--; + // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + --p; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + i = p[1]; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] +} + +void okey() { + int a[3]; + i = a[2]; //OK, access to array + + i++; + ++i; + i--; + --i; + i += 1; + i -= 1; + i = j + 1; + i = j - 1; + + auto diff = p - q; //OK, result is arithmetic +}