11#include "clang/AST/ASTContext.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13#include "clang/Lex/Lexer.h"
34 0, expr(hasType(cxxRecordDecl(hasName(
"::absl::Duration"))))),
35 hasArgument(1, expr().bind(
"arg")),
37 hasParent(functionTemplateDecl()),
38 unless(hasTemplateArgument(0, refersToType(builtinType()))),
39 hasAnyName(
"operator*=",
"operator/="))))
48 ofClass(cxxRecordDecl(hasName(
"::absl::Duration"))),
49 hasParent(functionTemplateDecl()),
50 unless(hasTemplateArgument(0, refersToType(builtinType()))),
51 hasAnyName(
"operator*=",
"operator/="))),
52 argumentCountIs(1), hasArgument(0, expr().bind(
"arg")))
60 callExpr(callee(functionDecl(
61 hasParent(functionTemplateDecl()),
62 unless(hasTemplateArgument(0, refersToType(builtinType()))),
63 hasAnyName(
"::absl::operator*",
"::absl::operator/"))),
65 hasArgument(0, expr(hasType(
66 cxxRecordDecl(hasName(
"::absl::Duration"))))),
67 hasArgument(1, expr().bind(
"arg")))
74 callExpr(callee(functionDecl(
75 hasParent(functionTemplateDecl()),
76 unless(hasTemplateArgument(0, refersToType(builtinType()))),
77 hasName(
"::absl::operator*"))),
78 argumentCountIs(2), hasArgument(0, expr().bind(
"arg")),
79 hasArgument(1, expr(hasType(
80 cxxRecordDecl(hasName(
"::absl::Duration"))))))
101 traverse(TK_AsIs, implicitCastExpr(
102 anyOf(hasCastKind(CK_UserDefinedConversion),
103 has(implicitCastExpr(
104 hasCastKind(CK_UserDefinedConversion)))),
107 DurationFactoryFunction(),
108 unless(hasParent(functionTemplateDecl())))),
109 hasArgument(0, expr().bind(
"arg")))))
115 const MatchFinder::MatchResult &Result) {
116 const llvm::StringRef Message =
117 "implicit conversion to 'int64_t' is deprecated in this context; use an "
118 "explicit cast instead";
120 TraversalKindScope RAII(*Result.Context, TK_AsIs);
122 const auto *ArgExpr = Result.Nodes.getNodeAs<Expr>(
"arg");
123 SourceLocation
Loc = ArgExpr->getBeginLoc();
125 const auto *OuterExpr = Result.Nodes.getNodeAs<Expr>(
"OuterExpr");
127 if (!match(isInTemplateInstantiation(), *OuterExpr, *Result.Context)
129 if (MatchedTemplateLocations.count(
Loc) == 0) {
142 internal::Matcher<Stmt> IsInsideTemplate =
143 hasAncestor(decl(anyOf(classTemplateDecl(), functionTemplateDecl())));
144 if (!match(IsInsideTemplate, *ArgExpr, *Result.Context).empty())
145 MatchedTemplateLocations.insert(
Loc);
147 DiagnosticBuilder Diag =
diag(
Loc, Message);
148 CharSourceRange SourceRange = Lexer::makeFileCharRange(
149 CharSourceRange::getTokenRange(ArgExpr->getSourceRange()),
150 *Result.SourceManager, Result.Context->getLangOpts());
151 if (SourceRange.isInvalid())
156 Diag << FixItHint::CreateInsertion(SourceRange.getBegin(),
157 "static_cast<int64_t>(")
158 << FixItHint::CreateInsertion(SourceRange.getEnd(),
")");
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.