1 //===--- ProBoundsPointerArithmeticCheck.cpp - clang-tidy------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "ProBoundsPointerArithmeticCheck.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 14 using namespace clang::ast_matchers; 15 16 namespace clang { 17 namespace tidy { 18 namespace cppcoreguidelines { 19 20 void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) { 21 if (!getLangOpts().CPlusPlus) 22 return; 23 24 const auto AllPointerTypes = anyOf( 25 hasType(pointerType()), hasType(autoType(hasDeducedType(pointerType()))), 26 hasType(decltypeType(hasUnderlyingType(pointerType())))); 27 28 // Flag all operators +, -, +=, -=, ++, -- that result in a pointer 29 Finder->addMatcher( 30 binaryOperator( 31 anyOf(hasOperatorName("+"), hasOperatorName("-"), 32 hasOperatorName("+="), hasOperatorName("-=")), 33 AllPointerTypes, 34 unless(hasLHS(ignoringImpCasts(declRefExpr(to(isImplicit())))))) 35 .bind("expr"), 36 this); 37 38 Finder->addMatcher( 39 unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), 40 hasType(pointerType())) 41 .bind("expr"), 42 this); 43 44 // Array subscript on a pointer (not an array) is also pointer arithmetic 45 Finder->addMatcher( 46 arraySubscriptExpr( 47 hasBase(ignoringImpCasts( 48 anyOf(AllPointerTypes, 49 hasType(decayedType(hasDecayedType(pointerType()))))))) 50 .bind("expr"), 51 this); 52 } 53 54 void ProBoundsPointerArithmeticCheck::check( 55 const MatchFinder::MatchResult &Result) { 56 const auto *MatchedExpr = Result.Nodes.getNodeAs<Expr>("expr"); 57 58 diag(MatchedExpr->getExprLoc(), "do not use pointer arithmetic"); 59 } 60 61 } // namespace cppcoreguidelines 62 } // namespace tidy 63 } // namespace clang 64