-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[clang-tidy] new check cppcoreguidelines-pro-bounds-pointer-arithmetic
Summary: 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 Depends on D13313 Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D13311 llvm-svn: 250116
- Loading branch information
Showing
7 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
//===--- 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; | ||
|
||
// Flag all operators +, -, +=, -=, ++, -- that result in a pointer | ||
Finder->addMatcher( | ||
binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-"), | ||
hasOperatorName("+="), hasOperatorName("-=")), | ||
hasType(pointerType())) | ||
.bind("expr"), | ||
this); | ||
|
||
Finder->addMatcher( | ||
unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), | ||
hasType(pointerType())) | ||
.bind("expr"), | ||
this); | ||
|
||
// Array subscript on a pointer (not an array) is also pointer arithmetic | ||
Finder->addMatcher( | ||
arraySubscriptExpr(hasBase(ignoringImpCasts(anyOf(hasType(pointerType()), | ||
hasType(decayedType(hasDecayedType(pointerType()))))))) | ||
.bind("expr"), | ||
this); | ||
} | ||
|
||
void | ||
ProBoundsPointerArithmeticCheck::check(const MatchFinder::MatchResult &Result) { | ||
const auto *MatchedExpr = Result.Nodes.getNodeAs<Expr>("expr"); | ||
|
||
diag(MatchedExpr->getExprLoc(), "do not use pointer arithmetic"); | ||
} | ||
|
||
} // namespace tidy | ||
} // namespace clang |
34 changes: 34 additions & 0 deletions
34
clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 that have result of pointer type, i.e. | ||
/// +, -, +=, -=, ++, --. In addition, the [] operator on pointers (not on arrays) is flagged. | ||
/// | ||
/// 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 |
10 changes: 10 additions & 0 deletions
10
...xtra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// 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 [cppcoreguidelines-pro-bounds-pointer-arithmetic] | ||
p = q + i; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic | ||
p = q + ENUM_LITERAL; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic | ||
|
||
q = p - 1; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic | ||
p = q - i; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic | ||
p = q - ENUM_LITERAL; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic | ||
|
||
p += 4; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic | ||
p += i; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic | ||
p += ENUM_LITERAL; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic | ||
|
||
q -= 1; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic | ||
q -= i; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic | ||
q -= ENUM_LITERAL; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic | ||
|
||
p++; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic | ||
++p; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic | ||
|
||
p--; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic | ||
--p; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic | ||
|
||
i = p[1]; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use pointer arithmetic | ||
} | ||
|
||
struct S { | ||
operator int() const; | ||
}; | ||
|
||
void f(S &s) { | ||
int *i; | ||
i = i + s; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic | ||
} | ||
|
||
void f2(int i[]) { | ||
i[1] = 0; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic | ||
} | ||
|
||
void okay() { | ||
int a[3]; | ||
i = a[2]; // OK, access to array | ||
|
||
p = q; | ||
p = &i; | ||
|
||
i++; | ||
++i; | ||
i--; | ||
--i; | ||
i += 1; | ||
i -= 1; | ||
i = j + 1; | ||
i = j - 1; | ||
|
||
auto diff = p - q; // OK, result is arithmetic | ||
} |