26 StrictMode(Options.get(
"StrictMode", false)),
27 StrFormatLikeFunctions(
utils::options::parseStringList(
28 Options.get(
"StrFormatLikeFunctions",
""))),
29 ReplacementFormatFunction(
30 Options.get(
"ReplacementFormatFunction",
"std::format")),
31 IncludeInserter(Options.getLocalOrGlobal(
"IncludeStyle",
32 utils::IncludeSorter::IS_LLVM),
33 areDiagsSelfContained()),
34 MaybeHeaderToInclude(Options.get(
"FormatHeader")) {
35 if (StrFormatLikeFunctions.empty())
36 StrFormatLikeFunctions.emplace_back(
"absl::StrFormat");
38 if (!MaybeHeaderToInclude && ReplacementFormatFunction ==
"std::format")
39 MaybeHeaderToInclude =
"<format>";
72 const unsigned FormatArgOffset = 0;
73 const auto *OldFunction = Result.Nodes.getNodeAs<FunctionDecl>(
"func_decl");
74 const auto *StrFormat = Result.Nodes.getNodeAs<CallExpr>(
"strformat");
79 Result.Context, StrFormat, FormatArgOffset, ConverterConfig,
80 getLangOpts(), *Result.SourceManager, *PP);
81 const Expr *StrFormatCall = StrFormat->getCallee();
83 diag(StrFormat->getBeginLoc(),
84 "unable to use '%0' instead of %1 because %2")
85 << StrFormatCall->getSourceRange() << ReplacementFormatFunction
86 << OldFunction->getIdentifier()
91 DiagnosticBuilder Diag =
92 diag(StrFormatCall->getBeginLoc(),
"use '%0' instead of %1")
93 << ReplacementFormatFunction << OldFunction->getIdentifier();
94 Diag << FixItHint::CreateReplacement(
95 CharSourceRange::getTokenRange(StrFormatCall->getExprLoc(),
96 StrFormatCall->getEndLoc()),
97 ReplacementFormatFunction);
98 Converter.
applyFixes(Diag, *Result.SourceManager);
100 if (MaybeHeaderToInclude)
101 Diag << IncludeInserter.createIncludeInsertion(
102 Result.Context->getSourceManager().getFileID(
103 StrFormatCall->getBeginLoc()),
104 *MaybeHeaderToInclude);
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.