11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Tooling/FixIt.h"
21 void DurationConversionCastCheck::registerMatchers(MatchFinder *Finder) {
22 auto CallMatcher = ignoringImpCasts(callExpr(
23 callee(functionDecl(DurationConversionFunction()).bind(
"func_decl")),
24 hasArgument(0, expr().bind(
"arg"))));
28 cxxStaticCastExpr(hasSourceExpression(CallMatcher)).bind(
"cast_expr"),
29 cStyleCastExpr(hasSourceExpression(CallMatcher)).bind(
"cast_expr"),
30 cxxFunctionalCastExpr(hasSourceExpression(CallMatcher))
35 void DurationConversionCastCheck::check(
36 const MatchFinder::MatchResult &Result) {
37 const auto *MatchedCast =
38 Result.Nodes.getNodeAs<ExplicitCastExpr>(
"cast_expr");
43 const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>(
"func_decl");
44 const auto *Arg = Result.Nodes.getNodeAs<Expr>(
"arg");
45 StringRef ConversionFuncName = FuncDecl->getName();
47 llvm::Optional<DurationScale> Scale =
53 if (MatchedCast->getTypeAsWritten()->isIntegerType() &&
54 ConversionFuncName.contains(
"Double")) {
57 diag(MatchedCast->getBeginLoc(),
58 "duration should be converted directly to an integer rather than "
59 "through a type cast")
60 << FixItHint::CreateReplacement(
61 MatchedCast->getSourceRange(),
62 (llvm::Twine(NewFuncName.substr(2)) +
"(" +
63 tooling::fixit::getText(*Arg, *Result.Context) +
")")
68 if (MatchedCast->getTypeAsWritten()->isRealFloatingType() &&
69 ConversionFuncName.contains(
"Int64")) {
72 diag(MatchedCast->getBeginLoc(),
"duration should be converted directly to "
73 "a floating-point number rather than "
74 "through a type cast")
75 << FixItHint::CreateReplacement(
76 MatchedCast->getSourceRange(),
77 (llvm::Twine(NewFuncName.substr(2)) +
"(" +
78 tooling::fixit::getText(*Arg, *Result.Context) +
")")