12 #include "clang/AST/ASTContext.h" 13 #include "clang/ASTMatchers/ASTMatchFinder.h" 21 void UpgradeDurationConversionsCheck::registerMatchers(MatchFinder *Finder) {
22 if (!getLangOpts().CPlusPlus)
39 0, expr(hasType(cxxRecordDecl(hasName(
"::absl::Duration"))))),
40 hasArgument(1, expr().bind(
"arg")),
42 hasParent(functionTemplateDecl()),
43 unless(hasTemplateArgument(0, refersToType(builtinType()))),
44 hasAnyName(
"operator*=",
"operator/=")))),
52 ofClass(cxxRecordDecl(hasName(
"::absl::Duration"))),
53 hasParent(functionTemplateDecl()),
54 unless(hasTemplateArgument(0, refersToType(builtinType()))),
55 hasAnyName(
"operator*=",
"operator/="))),
56 argumentCountIs(1), hasArgument(0, expr().bind(
"arg"))),
63 callExpr(callee(functionDecl(
64 hasParent(functionTemplateDecl()),
65 unless(hasTemplateArgument(0, refersToType(builtinType()))),
66 hasAnyName(
"::absl::operator*",
"::absl::operator/"))),
68 hasArgument(0, expr(hasType(
69 cxxRecordDecl(hasName(
"::absl::Duration"))))),
70 hasArgument(1, expr().bind(
"arg"))),
76 callExpr(callee(functionDecl(
77 hasParent(functionTemplateDecl()),
78 unless(hasTemplateArgument(0, refersToType(builtinType()))),
79 hasName(
"::absl::operator*"))),
80 argumentCountIs(2), hasArgument(0, expr().bind(
"arg")),
81 hasArgument(1, expr(hasType(cxxRecordDecl(
82 hasName(
"::absl::Duration")))))),
103 anyOf(hasCastKind(CK_UserDefinedConversion),
104 has(implicitCastExpr(hasCastKind(CK_UserDefinedConversion)))),
106 callee(functionDecl(DurationFactoryFunction(),
107 unless(hasParent(functionTemplateDecl())))),
108 hasArgument(0, expr().bind(
"arg"))))),
112 void UpgradeDurationConversionsCheck::check(
113 const MatchFinder::MatchResult &
Result) {
114 const llvm::StringRef
Message =
115 "implicit conversion to 'int64_t' is deprecated in this context; use an " 116 "explicit cast instead";
118 const auto *ArgExpr = Result.Nodes.getNodeAs<Expr>(
"arg");
119 SourceLocation
Loc = ArgExpr->getBeginLoc();
121 if (!match(isInTemplateInstantiation(), *ArgExpr, *Result.Context).empty()) {
122 if (MatchedTemplateLocations.count(Loc.getRawEncoding()) == 0) {
135 internal::Matcher<Stmt> IsInsideTemplate =
136 hasAncestor(decl(anyOf(classTemplateDecl(), functionTemplateDecl())));
137 if (!match(IsInsideTemplate, *ArgExpr, *Result.Context).empty())
138 MatchedTemplateLocations.insert(Loc.getRawEncoding());
140 DiagnosticBuilder Diag = diag(Loc, Message);
141 CharSourceRange SourceRange = Lexer::makeFileCharRange(
142 CharSourceRange::getTokenRange(ArgExpr->getSourceRange()),
143 *Result.SourceManager, Result.Context->getLangOpts());
144 if (SourceRange.isInvalid())
149 Diag << FixItHint::CreateInsertion(SourceRange.getBegin(),
150 "static_cast<int64_t>(")
151 << FixItHint::CreateInsertion(SourceRange.getEnd(),
")");
SourceLocation Loc
'#' location in the include directive
static const StringRef Message
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//