11#include "clang/AST/ASTContext.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13#include "clang/Lex/Lexer.h"
14#include "clang/Tooling/FixIt.h"
24 return !clang::Lexer::makeFileCharRange(
25 clang::CharSourceRange::getCharRange(
Range),
26 *Result.SourceManager, Result.Context->getLangOpts())
36 return selectFirst<const Expr>(
39 callExpr(hasParent(materializeTemporaryExpr(hasParent(
40 cxxConstructExpr(hasParent(exprWithCleanups(
41 hasParent(varDecl()))))))))
43 callExpr(hasParent(varDecl())).bind(
"e"))),
44 *
Node, *Result.Context)) !=
nullptr;
47static bool isArgument(
const MatchFinder::MatchResult &Result,
51 return selectFirst<const Expr>(
55 expr(hasParent(materializeTemporaryExpr(
56 hasParent(cxxConstructExpr(
57 hasParent(callExpr()),
58 unless(hasParent(cxxOperatorCallExpr())))))))
60 expr(hasParent(callExpr()),
61 unless(hasParent(cxxOperatorCallExpr())))
63 *
Node, *Result.Context)) !=
nullptr;
66static bool isReturn(
const MatchFinder::MatchResult &Result,
const Expr *Node) {
69 return selectFirst<const Expr>(
72 expr(hasParent(materializeTemporaryExpr(hasParent(
73 cxxConstructExpr(hasParent(exprWithCleanups(
74 hasParent(returnStmt()))))))))
76 expr(hasParent(returnStmt())).bind(
"e"))),
77 *
Node, *Result.Context)) !=
nullptr;
88void TimeSubtractionCheck::emitDiagnostic(
const Expr *Node,
89 llvm::StringRef Replacement) {
90 diag(
Node->getBeginLoc(),
"perform subtraction in the time domain")
91 << FixItHint::CreateReplacement(
Node->getSourceRange(), Replacement);
95 for (
const char *ScaleName :
96 {
"Hours",
"Minutes",
"Seconds",
"Millis",
"Micros",
"Nanos"}) {
97 std::string TimeInverse = (llvm::Twine(
"ToUnix") + ScaleName).str();
99 assert(Scale &&
"Unknown scale encountered");
101 auto TimeInverseMatcher = callExpr(callee(
102 functionDecl(hasName((llvm::Twine(
"::absl::") + TimeInverse).str()))
103 .bind(
"func_decl")));
113 hasArgument(0, binaryOperator(hasOperatorName(
"-"),
114 hasLHS(TimeInverseMatcher))
117 Finder->addMatcher(CallMatcher,
this);
122 auto OperandMatcher =
123 binaryOperator(hasOperatorName(
"-"), hasRHS(TimeInverseMatcher))
125 Finder->addMatcher(OperandMatcher,
this);
130 const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>(
"binop");
131 std::string InverseName =
132 Result.Nodes.getNodeAs<FunctionDecl>(
"func_decl")->getNameAsString();
140 const auto *OuterCall = Result.Nodes.getNodeAs<CallExpr>(
"outer_call");
152 (llvm::Twine(NeedParens ?
"(" :
"") +
155 (NeedParens ?
")" :
""))
161 const auto *MaybeCallArg = selectFirst<const CallExpr>(
162 "arg", match(expr(hasAncestor(
163 callExpr(callee(functionDecl(hasName(
166 *BinOp, *Result.Context));
167 if (MaybeCallArg && MaybeCallArg->getArg(0)->IgnoreImpCasts() == BinOp &&
177 (llvm::Twine(NeedParens ?
"(" :
"") +
181 (NeedParens ?
")" :
""))
CharSourceRange Range
SourceRange for the file name.
::clang::DynTypedNode Node
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
const std::pair< llvm::StringRef, llvm::StringRef > & getDurationInverseForScale(DurationScale Scale)
Given a Scale return the fully qualified inverse functions for it.
std::optional< DurationScale > getScaleForTimeInverse(llvm::StringRef Name)
Given the name of an inverse Time function (e.g., ToUnixSeconds), return its DurationScale,...
static bool isConstructorAssignment(const MatchFinder::MatchResult &Result, const Expr *Node)
static bool parensRequired(const MatchFinder::MatchResult &Result, const Expr *Node)
static bool isArgument(const MatchFinder::MatchResult &Result, const Expr *Node)
llvm::StringRef getDurationFactoryForScale(DurationScale Scale)
Returns the factory function name for a given Scale.
static bool isReturn(const MatchFinder::MatchResult &Result, const Expr *Node)
static bool insideMacroDefinition(const MatchFinder::MatchResult &Result, SourceRange Range)
std::string rewriteExprFromNumberToTime(const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale, const Expr *Node)
Assuming Node has a type int representing a time instant of Scale since The Epoch,...