clang-tools  3.9.0
PointerAndIntegralOperationCheck.cpp
Go to the documentation of this file.
1 //===--- PointerAndIntegralOperationCheck.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 
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "../utils/Matchers.h"
14 
15 using namespace clang::ast_matchers;
16 
17 namespace clang {
18 namespace tidy {
19 namespace misc {
20 
21 void PointerAndIntegralOperationCheck::registerMatchers(MatchFinder *Finder) {
22  const auto PointerExpr = expr(hasType(pointerType()));
23  const auto BoolExpr = ignoringParenImpCasts(hasType(booleanType()));
24  const auto CharExpr = ignoringParenImpCasts(hasType(isAnyCharacter()));
25 
26  const auto BinOpWithPointerExpr =
27  binaryOperator(unless(anyOf(hasOperatorName(","), hasOperatorName("="))),
28  hasEitherOperand(PointerExpr));
29 
30  const auto AssignToPointerExpr =
31  binaryOperator(hasOperatorName("="), hasLHS(PointerExpr));
32 
33  const auto CompareToPointerExpr =
34  binaryOperator(matchers::isRelationalOperator(),
35  hasEitherOperand(PointerExpr));
36 
37  // Detect expression like: ptr = (x != y);
38  Finder->addMatcher(binaryOperator(AssignToPointerExpr, hasRHS(BoolExpr))
39  .bind("assign-bool-to-pointer"),
40  this);
41 
42  // Detect expression like: ptr = A[i]; where A is char*.
43  Finder->addMatcher(binaryOperator(AssignToPointerExpr, hasRHS(CharExpr))
44  .bind("assign-char-to-pointer"),
45  this);
46 
47  // Detect expression like: ptr < false;
48  Finder->addMatcher(
49  binaryOperator(BinOpWithPointerExpr,
50  hasEitherOperand(ignoringParenImpCasts(cxxBoolLiteral())))
51  .bind("pointer-and-bool-literal"),
52  this);
53 
54  // Detect expression like: ptr < 'a';
55  Finder->addMatcher(binaryOperator(BinOpWithPointerExpr,
56  hasEitherOperand(ignoringParenImpCasts(
57  characterLiteral())))
58  .bind("pointer-and-char-literal"),
59  this);
60 
61  // Detect expression like: ptr < 0;
62  Finder->addMatcher(binaryOperator(CompareToPointerExpr,
63  hasEitherOperand(ignoringParenImpCasts(
64  integerLiteral(equals(0)))))
65  .bind("compare-pointer-to-zero"),
66  this);
67 
68  // Detect expression like: ptr < nullptr;
69  Finder->addMatcher(binaryOperator(CompareToPointerExpr,
70  hasEitherOperand(ignoringParenImpCasts(
71  cxxNullPtrLiteralExpr())))
72  .bind("compare-pointer-to-null"),
73  this);
74 }
75 
76 void PointerAndIntegralOperationCheck::check(
77  const MatchFinder::MatchResult &Result) {
78  if (const auto *E =
79  Result.Nodes.getNodeAs<BinaryOperator>("assign-bool-to-pointer")) {
80  diag(E->getOperatorLoc(), "suspicious assignment from bool to pointer");
81  } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
82  "assign-char-to-pointer")) {
83  diag(E->getOperatorLoc(), "suspicious assignment from char to pointer");
84  } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
85  "pointer-and-bool-literal")) {
86  diag(E->getOperatorLoc(),
87  "suspicious operation between pointer and bool literal");
88  } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
89  "pointer-and-char-literal")) {
90  diag(E->getOperatorLoc(),
91  "suspicious operation between pointer and character literal");
92  } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
93  "compare-pointer-to-zero")) {
94  diag(E->getOperatorLoc(), "suspicious comparison of pointer with zero");
95  } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
96  "compare-pointer-to-null")) {
97  diag(E->getOperatorLoc(),
98  "suspicious comparison of pointer with null expression");
99  }
100 }
101 
102 } // namespace misc
103 } // namespace tidy
104 } // namespace clang
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:210
const NamedDecl * Result
Definition: USRFinder.cpp:137