//===--- 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("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 SimpleArg = stripFloatCast(Result, *Arg); if (!SimpleArg) SimpleArg = stripFloatLiteralFraction(Result, *Arg); if (SimpleArg) { diag(MatchedCall->getBeginLoc(), (llvm::Twine("use the integer version of absl::") + MatchedCall->getDirectCallee()->getName()) .str()) << FixItHint::CreateReplacement(Arg->getSourceRange(), *SimpleArg); } } } // namespace abseil } // namespace tidy } // namespace clang