• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- DurationFactoryFloatCheck.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 "DurationFactoryFloatCheck.h"
10 #include "DurationRewriter.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14 #include "clang/Tooling/FixIt.h"
15 
16 using namespace clang::ast_matchers;
17 
18 namespace clang {
19 namespace tidy {
20 namespace abseil {
21 
22 // Returns `true` if `Range` is inside a macro definition.
InsideMacroDefinition(const MatchFinder::MatchResult & Result,SourceRange Range)23 static bool InsideMacroDefinition(const MatchFinder::MatchResult &Result,
24                                   SourceRange Range) {
25   return !clang::Lexer::makeFileCharRange(
26               clang::CharSourceRange::getCharRange(Range),
27               *Result.SourceManager, Result.Context->getLangOpts())
28               .isValid();
29 }
30 
registerMatchers(MatchFinder * Finder)31 void DurationFactoryFloatCheck::registerMatchers(MatchFinder *Finder) {
32   Finder->addMatcher(
33       callExpr(callee(functionDecl(DurationFactoryFunction())),
34                hasArgument(0, anyOf(cxxStaticCastExpr(hasDestinationType(
35                                         realFloatingPointType())),
36                                     cStyleCastExpr(hasDestinationType(
37                                         realFloatingPointType())),
38                                     cxxFunctionalCastExpr(hasDestinationType(
39                                         realFloatingPointType())),
40                                     floatLiteral())))
41           .bind("call"),
42       this);
43 }
44 
check(const MatchFinder::MatchResult & Result)45 void DurationFactoryFloatCheck::check(const MatchFinder::MatchResult &Result) {
46   const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>("call");
47 
48   // Don't try and replace things inside of macro definitions.
49   if (InsideMacroDefinition(Result, MatchedCall->getSourceRange()))
50     return;
51 
52   const Expr *Arg = MatchedCall->getArg(0)->IgnoreImpCasts();
53   // Arguments which are macros are ignored.
54   if (Arg->getBeginLoc().isMacroID())
55     return;
56 
57   llvm::Optional<std::string> SimpleArg = stripFloatCast(Result, *Arg);
58   if (!SimpleArg)
59     SimpleArg = stripFloatLiteralFraction(Result, *Arg);
60 
61   if (SimpleArg) {
62     diag(MatchedCall->getBeginLoc(),
63          (llvm::Twine("use the integer version of absl::") +
64           MatchedCall->getDirectCallee()->getName())
65              .str())
66         << FixItHint::CreateReplacement(Arg->getSourceRange(), *SimpleArg);
67   }
68 }
69 
70 } // namespace abseil
71 } // namespace tidy
72 } // namespace clang
73