11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 20 void UpgradeDurationConversionsCheck::registerMatchers(MatchFinder *Finder) {
21 if (!getLangOpts().CPlusPlus)
38 0, expr(hasType(cxxRecordDecl(hasName(
"::absl::Duration"))))),
39 hasArgument(1, expr().bind(
"arg")),
41 hasParent(functionTemplateDecl()),
42 unless(hasTemplateArgument(0, refersToType(builtinType()))),
43 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")))
64 callExpr(callee(functionDecl(
65 hasParent(functionTemplateDecl()),
66 unless(hasTemplateArgument(0, refersToType(builtinType()))),
67 hasAnyName(
"::absl::operator*",
"::absl::operator/"))),
69 hasArgument(0, expr(hasType(
70 cxxRecordDecl(hasName(
"::absl::Duration"))))),
71 hasArgument(1, expr().bind(
"arg")))
78 callExpr(callee(functionDecl(
79 hasParent(functionTemplateDecl()),
80 unless(hasTemplateArgument(0, refersToType(builtinType()))),
81 hasName(
"::absl::operator*"))),
82 argumentCountIs(2), hasArgument(0, expr().bind(
"arg")),
83 hasArgument(1, expr(hasType(
84 cxxRecordDecl(hasName(
"::absl::Duration"))))))
106 anyOf(hasCastKind(CK_UserDefinedConversion),
107 has(implicitCastExpr(hasCastKind(CK_UserDefinedConversion)))),
109 callee(functionDecl(DurationFactoryFunction(),
110 unless(hasParent(functionTemplateDecl())))),
111 hasArgument(0, expr().bind(
"arg")))))
116 void UpgradeDurationConversionsCheck::check(
117 const MatchFinder::MatchResult &Result) {
118 const llvm::StringRef
Message =
119 "implicit conversion to 'int64_t' is deprecated in this context; use an " 120 "explicit cast instead";
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.getRawEncoding()) == 0) {
142 internal::Matcher<Stmt> IsInsideTemplate =
143 hasAncestor(decl(anyOf(classTemplateDecl(), functionTemplateDecl())));
144 if (!
match(IsInsideTemplate, *ArgExpr, *Result.Context).empty())
145 MatchedTemplateLocations.insert(Loc.getRawEncoding());
147 DiagnosticBuilder Diag = diag(Loc, Message);
148 CharSourceRange SourceRange = Lexer::makeFileCharRange(
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(),
")");
SourceLocation Loc
'#' location in the include directive
constexpr llvm::StringLiteral Message
std::vector< std::string > match(const SymbolIndex &I, const FuzzyFindRequest &Req, bool *Incomplete)
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//