| //===--- DurationFactoryFloatCheck.cpp - clang-tidy -----------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "DurationFactoryFloatCheck.h" |
| #include "DurationRewriter.h" |
| #include "clang/AST/ASTContext.h" |
| #include "clang/ASTMatchers/ASTMatchFinder.h" |
| #include "clang/Lex/Lexer.h" |
| #include "clang/Tooling/FixIt.h" |
| |
| using namespace clang::ast_matchers; |
| |
| namespace clang { |
| namespace tidy { |
| namespace abseil { |
| |
| // Returns `true` if `Range` is inside a macro definition. |
| static bool insideMacroDefinition(const MatchFinder::MatchResult &Result, |
| SourceRange Range) { |
| return !clang::Lexer::makeFileCharRange( |
| clang::CharSourceRange::getCharRange(Range), |
| *Result.SourceManager, Result.Context->getLangOpts()) |
| .isValid(); |
| } |
| |
| void DurationFactoryFloatCheck::registerMatchers(MatchFinder *Finder) { |
| Finder->addMatcher( |
| callExpr(callee(functionDecl(DurationFactoryFunction())), |
| hasArgument(0, anyOf(cxxStaticCastExpr(hasDestinationType( |
| realFloatingPointType())), |
| cStyleCastExpr(hasDestinationType( |
| realFloatingPointType())), |
| cxxFunctionalCastExpr(hasDestinationType( |
| realFloatingPointType())), |
| floatLiteral()))) |
| .bind("call"), |
| this); |
| } |
| |
| void DurationFactoryFloatCheck::check(const MatchFinder::MatchResult &Result) { |
| const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>("call"); |
| |
| // Don't try and replace things inside of macro definitions. |
| if (insideMacroDefinition(Result, MatchedCall->getSourceRange())) |
| return; |
| |
| const Expr *Arg = MatchedCall->getArg(0)->IgnoreImpCasts(); |
| // Arguments which are macros are ignored. |
| if (Arg->getBeginLoc().isMacroID()) |
| return; |
| |
| llvm::Optional<std::string> SimpleArg = stripFloatCast(Result, *Arg); |
| if (!SimpleArg) |
| SimpleArg = stripFloatLiteralFraction(Result, *Arg); |
| |
| if (SimpleArg) { |
| diag(MatchedCall->getBeginLoc(), "use the integer version of absl::%0") |
| << MatchedCall->getDirectCallee()->getName() |
| << FixItHint::CreateReplacement(Arg->getSourceRange(), *SimpleArg); |
| } |
| } |
| |
| } // namespace abseil |
| } // namespace tidy |
| } // namespace clang |