20 for (
const auto &Scale : {
"Hours",
"Minutes",
"Seconds",
"Milliseconds",
21 "Microseconds",
"Nanoseconds"}) {
22 std::string DurationFactory = (llvm::Twine(
"::absl::") + Scale).str();
23 std::string FloatConversion =
24 (llvm::Twine(
"::absl::ToDouble") + Scale).str();
25 std::string IntegerConversion =
26 (llvm::Twine(
"::absl::ToInt64") + Scale).str();
30 auto FactoryMatcher = ignoringElidableConstructorCall(
31 callExpr(callee(functionDecl(hasName(DurationFactory))),
32 hasArgument(0, ignoringImpCasts(integerLiteral(equals(1))))));
36 auto InverseFunctionMatcher = callExpr(
37 callee(functionDecl(hasAnyName(FloatConversion, IntegerConversion))),
38 hasArgument(0, expr().bind(
"arg")));
42 auto DivisionOperatorMatcher = cxxOperatorCallExpr(
43 hasOverloadedOperatorName(
"/"), hasArgument(0, expr().bind(
"arg")),
44 hasArgument(1, FactoryMatcher));
48 auto FdivMatcher = callExpr(
49 callee(functionDecl(hasName(
"::absl::FDivDuration"))),
50 hasArgument(0, expr().bind(
"arg")), hasArgument(1, FactoryMatcher));
54 auto ScalarMatcher = ignoringImpCasts(
55 binaryOperator(hasOperatorName(
"*"),
56 hasEitherOperand(expr(ignoringParenImpCasts(
57 callExpr(callee(functionDecl(hasAnyName(
58 FloatConversion, IntegerConversion))),
59 hasArgument(0, expr().bind(
"arg")))
60 .bind(
"inner_call")))))
64 callExpr(callee(functionDecl(hasName(DurationFactory))),
65 hasArgument(0, anyOf(InverseFunctionMatcher,
66 DivisionOperatorMatcher, FdivMatcher,
74 const MatchFinder::MatchResult &Result) {
75 const auto *OuterCall = Result.Nodes.getNodeAs<Expr>(
"call");
81 if (
const auto *Binop = Result.Nodes.getNodeAs<BinaryOperator>(
"binop")) {
82 const auto *Arg = Result.Nodes.getNodeAs<Expr>(
"arg");
83 const auto *InnerCall = Result.Nodes.getNodeAs<Expr>(
"inner_call");
84 const Expr *LHS = Binop->getLHS();
85 const Expr *RHS = Binop->getRHS();
87 if (LHS->IgnoreParenImpCasts() == InnerCall) {
88 Hint = FixItHint::CreateReplacement(
89 OuterCall->getSourceRange(),
90 (llvm::Twine(tooling::fixit::getText(*Arg, *Result.Context)) +
" * " +
91 tooling::fixit::getText(*RHS, *Result.Context))
94 assert(RHS->IgnoreParenImpCasts() == InnerCall &&
95 "Inner call should be find on the RHS");
97 Hint = FixItHint::CreateReplacement(
98 OuterCall->getSourceRange(),
99 (llvm::Twine(tooling::fixit::getText(*LHS, *Result.Context)) +
" * " +
100 tooling::fixit::getText(*Arg, *Result.Context))
103 }
else if (
const auto *Arg = Result.Nodes.getNodeAs<Expr>(
"arg")) {
104 Hint = FixItHint::CreateReplacement(
105 OuterCall->getSourceRange(),
106 tooling::fixit::getText(*Arg, *Result.Context));
108 diag(OuterCall->getBeginLoc(),
109 "remove unnecessary absl::Duration conversions")