1 //===--- IntegerDivisionCheck.cpp - clang-tidy-----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "IntegerDivisionCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 
13 using namespace clang::ast_matchers;
14 
15 namespace clang {
16 namespace tidy {
17 namespace bugprone {
18 
19 void IntegerDivisionCheck::registerMatchers(MatchFinder *Finder) {
20   const auto IntType = hasType(isInteger());
21 
22   const auto BinaryOperators = binaryOperator(anyOf(
23       hasOperatorName("%"), hasOperatorName("<<"), hasOperatorName(">>"),
24       hasOperatorName("<<"), hasOperatorName("^"), hasOperatorName("|"),
25       hasOperatorName("&"), hasOperatorName("||"), hasOperatorName("&&"),
26       hasOperatorName("<"), hasOperatorName(">"), hasOperatorName("<="),
27       hasOperatorName(">="), hasOperatorName("=="), hasOperatorName("!=")));
28 
29   const auto UnaryOperators =
30       unaryOperator(anyOf(hasOperatorName("~"), hasOperatorName("!")));
31 
32   const auto Exceptions =
33       anyOf(BinaryOperators, conditionalOperator(), binaryConditionalOperator(),
34             callExpr(IntType), explicitCastExpr(IntType), UnaryOperators);
35 
36   Finder->addMatcher(
37       binaryOperator(
38           hasOperatorName("/"), hasLHS(expr(IntType)), hasRHS(expr(IntType)),
39           hasAncestor(
40               castExpr(hasCastKind(CK_IntegralToFloating)).bind("FloatCast")),
41           unless(hasAncestor(
42               expr(Exceptions,
43                    hasAncestor(castExpr(equalsBoundNode("FloatCast")))))))
44           .bind("IntDiv"),
45       this);
46 }
47 
48 void IntegerDivisionCheck::check(const MatchFinder::MatchResult &Result) {
49   const auto *IntDiv = Result.Nodes.getNodeAs<BinaryOperator>("IntDiv");
50   diag(IntDiv->getBeginLoc(), "result of integer division used in a floating "
51                               "point context; possible loss of precision");
52 }
53 
54 } // namespace bugprone
55 } // namespace tidy
56 } // namespace clang
57