clang-tools  7.0.0
NarrowingConversionsCheck.cpp
Go to the documentation of this file.
1 //===--- NarrowingConversionsCheck.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 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace cppcoreguidelines {
19 
20 // FIXME: Check double -> float truncation. Pay attention to casts:
21 void NarrowingConversionsCheck::registerMatchers(MatchFinder *Finder) {
22  // ceil() and floor() are guaranteed to return integers, even though the type
23  // is not integral.
24  const auto IsCeilFloorCall = callExpr(callee(functionDecl(
25  hasAnyName("::ceil", "::std::ceil", "::floor", "::std::floor"))));
26 
27  const auto IsFloatExpr =
28  expr(hasType(realFloatingPointType()), unless(IsCeilFloorCall));
29 
30  // casts:
31  // i = 0.5;
32  // void f(int); f(0.5);
33  Finder->addMatcher(implicitCastExpr(hasImplicitDestinationType(isInteger()),
34  hasSourceExpression(IsFloatExpr),
35  unless(hasParent(castExpr())),
36  unless(isInTemplateInstantiation()))
37  .bind("cast"),
38  this);
39 
40  // Binary operators:
41  // i += 0.5;
42  Finder->addMatcher(
43  binaryOperator(isAssignmentOperator(),
44  // The `=` case generates an implicit cast which is covered
45  // by the previous matcher.
46  unless(hasOperatorName("=")),
47  hasLHS(hasType(isInteger())), hasRHS(IsFloatExpr),
48  unless(isInTemplateInstantiation()))
49  .bind("op"),
50  this);
51 }
52 
53 void NarrowingConversionsCheck::check(const MatchFinder::MatchResult &Result) {
54  if (const auto *Op = Result.Nodes.getNodeAs<BinaryOperator>("op")) {
55  if (Op->getLocStart().isMacroID())
56  return;
57  diag(Op->getOperatorLoc(), "narrowing conversion from %0 to %1")
58  << Op->getRHS()->getType() << Op->getLHS()->getType();
59  return;
60  }
61  const auto *Cast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast");
62  if (Cast->getLocStart().isMacroID())
63  return;
64  diag(Cast->getExprLoc(), "narrowing conversion from %0 to %1")
65  << Cast->getSubExpr()->getType() << Cast->getType();
66 }
67 
68 } // namespace cppcoreguidelines
69 } // namespace tidy
70 } // namespace clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//