[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / clang-tools-extra / clang-tidy / utils / FormatStringConverter.cpp
blob951e0acf79b1ae328cb085dc63200c62d608a17d
1 //===--- FormatStringConverter.cpp - clang-tidy----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// Implementation of the FormatStringConverter class which is used to convert
11 /// printf format strings to C++ std::formatter format strings.
12 ///
13 //===----------------------------------------------------------------------===//
15 #include "FormatStringConverter.h"
16 #include "../utils/FixItHintUtils.h"
17 #include "clang/AST/Expr.h"
18 #include "clang/ASTMatchers/ASTMatchFinder.h"
19 #include "clang/Basic/LangOptions.h"
20 #include "clang/Lex/Lexer.h"
21 #include "clang/Tooling/FixIt.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/Support/Debug.h"
25 using namespace clang::ast_matchers;
26 using namespace clang::analyze_printf;
28 namespace clang::tidy::utils {
29 using clang::analyze_format_string::ConversionSpecifier;
31 /// Is the passed type the actual "char" type, whether that be signed or
32 /// unsigned, rather than explicit signed char or unsigned char types.
33 static bool isRealCharType(const clang::QualType &Ty) {
34 using namespace clang;
35 const Type *DesugaredType = Ty->getUnqualifiedDesugaredType();
36 if (const auto *BT = llvm::dyn_cast<BuiltinType>(DesugaredType))
37 return (BT->getKind() == BuiltinType::Char_U ||
38 BT->getKind() == BuiltinType::Char_S);
39 return false;
42 /// If possible, return the text name of the signed type that corresponds to the
43 /// passed integer type. If the passed type is already signed then its name is
44 /// just returned. Only supports BuiltinTypes.
45 static std::optional<std::string>
46 getCorrespondingSignedTypeName(const clang::QualType &QT) {
47 using namespace clang;
48 const auto UQT = QT.getUnqualifiedType();
49 if (const auto *BT = llvm::dyn_cast<BuiltinType>(UQT)) {
50 switch (BT->getKind()) {
51 case BuiltinType::UChar:
52 case BuiltinType::Char_U:
53 case BuiltinType::SChar:
54 case BuiltinType::Char_S:
55 return "signed char";
56 case BuiltinType::UShort:
57 case BuiltinType::Short:
58 return "short";
59 case BuiltinType::UInt:
60 case BuiltinType::Int:
61 return "int";
62 case BuiltinType::ULong:
63 case BuiltinType::Long:
64 return "long";
65 case BuiltinType::ULongLong:
66 case BuiltinType::LongLong:
67 return "long long";
68 default:
69 llvm::dbgs() << "Unknown corresponding signed type for BuiltinType '"
70 << QT.getAsString() << "'\n";
71 return std::nullopt;
75 // Deal with fixed-width integer types from <cstdint>. Use std:: prefix only
76 // if the argument type does.
77 const std::string TypeName = UQT.getAsString();
78 StringRef SimplifiedTypeName{TypeName};
79 const bool InStd = SimplifiedTypeName.consume_front("std::");
80 const StringRef Prefix = InStd ? "std::" : "";
82 if (SimplifiedTypeName.starts_with("uint") &&
83 SimplifiedTypeName.ends_with("_t"))
84 return (Twine(Prefix) + SimplifiedTypeName.drop_front()).str();
86 if (SimplifiedTypeName == "size_t")
87 return (Twine(Prefix) + "ssize_t").str();
89 llvm::dbgs() << "Unknown corresponding signed type for non-BuiltinType '"
90 << UQT.getAsString() << "'\n";
91 return std::nullopt;
94 /// If possible, return the text name of the unsigned type that corresponds to
95 /// the passed integer type. If the passed type is already unsigned then its
96 /// name is just returned. Only supports BuiltinTypes.
97 static std::optional<std::string>
98 getCorrespondingUnsignedTypeName(const clang::QualType &QT) {
99 using namespace clang;
100 const auto UQT = QT.getUnqualifiedType();
101 if (const auto *BT = llvm::dyn_cast<BuiltinType>(UQT)) {
102 switch (BT->getKind()) {
103 case BuiltinType::SChar:
104 case BuiltinType::Char_S:
105 case BuiltinType::UChar:
106 case BuiltinType::Char_U:
107 return "unsigned char";
108 case BuiltinType::Short:
109 case BuiltinType::UShort:
110 return "unsigned short";
111 case BuiltinType::Int:
112 case BuiltinType::UInt:
113 return "unsigned int";
114 case BuiltinType::Long:
115 case BuiltinType::ULong:
116 return "unsigned long";
117 case BuiltinType::LongLong:
118 case BuiltinType::ULongLong:
119 return "unsigned long long";
120 default:
121 llvm::dbgs() << "Unknown corresponding unsigned type for BuiltinType '"
122 << UQT.getAsString() << "'\n";
123 return std::nullopt;
127 // Deal with fixed-width integer types from <cstdint>. Use std:: prefix only
128 // if the argument type does.
129 const std::string TypeName = UQT.getAsString();
130 StringRef SimplifiedTypeName{TypeName};
131 const bool InStd = SimplifiedTypeName.consume_front("std::");
132 const StringRef Prefix = InStd ? "std::" : "";
134 if (SimplifiedTypeName.starts_with("int") &&
135 SimplifiedTypeName.ends_with("_t"))
136 return (Twine(Prefix) + "u" + SimplifiedTypeName).str();
138 if (SimplifiedTypeName == "ssize_t")
139 return (Twine(Prefix) + "size_t").str();
140 if (SimplifiedTypeName == "ptrdiff_t")
141 return (Twine(Prefix) + "size_t").str();
143 llvm::dbgs() << "Unknown corresponding unsigned type for non-BuiltinType '"
144 << UQT.getAsString() << "'\n";
145 return std::nullopt;
148 static std::optional<std::string>
149 castTypeForArgument(ConversionSpecifier::Kind ArgKind,
150 const clang::QualType &QT) {
151 if (ArgKind == ConversionSpecifier::Kind::uArg)
152 return getCorrespondingUnsignedTypeName(QT);
153 return getCorrespondingSignedTypeName(QT);
156 static bool isMatchingSignedness(ConversionSpecifier::Kind ArgKind,
157 const clang::QualType &ArgType) {
158 if (const auto *BT = llvm::dyn_cast<BuiltinType>(ArgType)) {
159 // Unadorned char never matches any expected signedness since it
160 // could be signed or unsigned.
161 const auto ArgTypeKind = BT->getKind();
162 if (ArgTypeKind == BuiltinType::Char_U ||
163 ArgTypeKind == BuiltinType::Char_S)
164 return false;
167 if (ArgKind == ConversionSpecifier::Kind::uArg)
168 return ArgType->isUnsignedIntegerType();
169 return ArgType->isSignedIntegerType();
172 namespace {
173 AST_MATCHER(clang::QualType, isRealChar) {
174 return clang::tidy::utils::isRealCharType(Node);
176 } // namespace
178 static bool castMismatchedIntegerTypes(const CallExpr *Call, bool StrictMode) {
179 /// For printf-style functions, the signedness of the type printed is
180 /// indicated by the corresponding type in the format string.
181 /// std::print will determine the signedness from the type of the
182 /// argument. This means that it is necessary to generate a cast in
183 /// StrictMode to ensure that the exact behaviour is maintained.
184 /// However, for templated functions like absl::PrintF and
185 /// fmt::printf, the signedness of the type printed is also taken from
186 /// the actual argument like std::print, so such casts are never
187 /// necessary. printf-style functions are variadic, whereas templated
188 /// ones aren't, so we can use that to distinguish between the two
189 /// cases.
190 if (StrictMode) {
191 const FunctionDecl *FuncDecl = Call->getDirectCallee();
192 assert(FuncDecl);
193 return FuncDecl->isVariadic();
195 return false;
198 FormatStringConverter::FormatStringConverter(ASTContext *ContextIn,
199 const CallExpr *Call,
200 unsigned FormatArgOffset,
201 bool StrictMode,
202 const LangOptions &LO)
203 : Context(ContextIn),
204 CastMismatchedIntegerTypes(castMismatchedIntegerTypes(Call, StrictMode)),
205 Args(Call->getArgs()), NumArgs(Call->getNumArgs()),
206 ArgsOffset(FormatArgOffset + 1), LangOpts(LO) {
207 assert(ArgsOffset <= NumArgs);
208 FormatExpr = llvm::dyn_cast<StringLiteral>(
209 Args[FormatArgOffset]->IgnoreImplicitAsWritten());
210 assert(FormatExpr);
211 if (!FormatExpr->isOrdinary())
212 return; // No wide string support yet
213 PrintfFormatString = FormatExpr->getString();
215 // Assume that the output will be approximately the same size as the input,
216 // but perhaps with a few escapes expanded.
217 const size_t EstimatedGrowth = 8;
218 StandardFormatString.reserve(PrintfFormatString.size() + EstimatedGrowth);
219 StandardFormatString.push_back('\"');
221 const bool IsFreeBsdkPrintf = false;
223 using clang::analyze_format_string::ParsePrintfString;
224 ParsePrintfString(*this, PrintfFormatString.data(),
225 PrintfFormatString.data() + PrintfFormatString.size(),
226 LangOpts, Context->getTargetInfo(), IsFreeBsdkPrintf);
227 finalizeFormatText();
230 void FormatStringConverter::emitAlignment(const PrintfSpecifier &FS,
231 std::string &FormatSpec) {
232 ConversionSpecifier::Kind ArgKind = FS.getConversionSpecifier().getKind();
234 // We only care about alignment if a field width is specified
235 if (FS.getFieldWidth().getHowSpecified() != OptionalAmount::NotSpecified) {
236 if (ArgKind == ConversionSpecifier::sArg) {
237 // Strings are left-aligned by default with std::format, so we only
238 // need to emit an alignment if this one needs to be right aligned.
239 if (!FS.isLeftJustified())
240 FormatSpec.push_back('>');
241 } else {
242 // Numbers are right-aligned by default with std::format, so we only
243 // need to emit an alignment if this one needs to be left aligned.
244 if (FS.isLeftJustified())
245 FormatSpec.push_back('<');
250 void FormatStringConverter::emitSign(const PrintfSpecifier &FS,
251 std::string &FormatSpec) {
252 const ConversionSpecifier Spec = FS.getConversionSpecifier();
254 // Ignore on something that isn't numeric. For printf it's would be a
255 // compile-time warning but ignored at runtime, but for std::format it
256 // ought to be a compile-time error.
257 if (Spec.isAnyIntArg() || Spec.isDoubleArg()) {
258 // + is preferred to ' '
259 if (FS.hasPlusPrefix())
260 FormatSpec.push_back('+');
261 else if (FS.hasSpacePrefix())
262 FormatSpec.push_back(' ');
266 void FormatStringConverter::emitAlternativeForm(const PrintfSpecifier &FS,
267 std::string &FormatSpec) {
268 if (FS.hasAlternativeForm()) {
269 switch (FS.getConversionSpecifier().getKind()) {
270 case ConversionSpecifier::Kind::aArg:
271 case ConversionSpecifier::Kind::AArg:
272 case ConversionSpecifier::Kind::eArg:
273 case ConversionSpecifier::Kind::EArg:
274 case ConversionSpecifier::Kind::fArg:
275 case ConversionSpecifier::Kind::FArg:
276 case ConversionSpecifier::Kind::gArg:
277 case ConversionSpecifier::Kind::GArg:
278 case ConversionSpecifier::Kind::xArg:
279 case ConversionSpecifier::Kind::XArg:
280 case ConversionSpecifier::Kind::oArg:
281 FormatSpec.push_back('#');
282 break;
283 default:
284 // Alternative forms don't exist for other argument kinds
285 break;
290 void FormatStringConverter::emitFieldWidth(const PrintfSpecifier &FS,
291 std::string &FormatSpec) {
293 const OptionalAmount FieldWidth = FS.getFieldWidth();
294 switch (FieldWidth.getHowSpecified()) {
295 case OptionalAmount::NotSpecified:
296 break;
297 case OptionalAmount::Constant:
298 FormatSpec.append(llvm::utostr(FieldWidth.getConstantAmount()));
299 break;
300 case OptionalAmount::Arg:
301 FormatSpec.push_back('{');
302 if (FieldWidth.usesPositionalArg()) {
303 // std::format argument identifiers are zero-based, whereas printf
304 // ones are one based.
305 assert(FieldWidth.getPositionalArgIndex() > 0U);
306 FormatSpec.append(llvm::utostr(FieldWidth.getPositionalArgIndex() - 1));
308 FormatSpec.push_back('}');
309 break;
310 case OptionalAmount::Invalid:
311 break;
316 void FormatStringConverter::emitPrecision(const PrintfSpecifier &FS,
317 std::string &FormatSpec) {
318 const OptionalAmount FieldPrecision = FS.getPrecision();
319 switch (FieldPrecision.getHowSpecified()) {
320 case OptionalAmount::NotSpecified:
321 break;
322 case OptionalAmount::Constant:
323 FormatSpec.push_back('.');
324 FormatSpec.append(llvm::utostr(FieldPrecision.getConstantAmount()));
325 break;
326 case OptionalAmount::Arg:
327 FormatSpec.push_back('.');
328 FormatSpec.push_back('{');
329 if (FieldPrecision.usesPositionalArg()) {
330 // std::format argument identifiers are zero-based, whereas printf
331 // ones are one based.
332 assert(FieldPrecision.getPositionalArgIndex() > 0U);
333 FormatSpec.append(
334 llvm::utostr(FieldPrecision.getPositionalArgIndex() - 1));
336 FormatSpec.push_back('}');
337 break;
338 case OptionalAmount::Invalid:
339 break;
343 void FormatStringConverter::maybeRotateArguments(const PrintfSpecifier &FS) {
344 unsigned ArgCount = 0;
345 const OptionalAmount FieldWidth = FS.getFieldWidth();
346 const OptionalAmount FieldPrecision = FS.getPrecision();
348 if (FieldWidth.getHowSpecified() == OptionalAmount::Arg &&
349 !FieldWidth.usesPositionalArg())
350 ++ArgCount;
351 if (FieldPrecision.getHowSpecified() == OptionalAmount::Arg &&
352 !FieldPrecision.usesPositionalArg())
353 ++ArgCount;
355 if (ArgCount)
356 ArgRotates.emplace_back(FS.getArgIndex() + ArgsOffset, ArgCount);
359 void FormatStringConverter::emitStringArgument(const Expr *Arg) {
360 // If the argument is the result of a call to std::string::c_str() or
361 // data() with a return type of char then we can remove that call and
362 // pass the std::string directly. We don't want to do so if the return
363 // type is not a char pointer (though it's unlikely that such code would
364 // compile without warnings anyway.) See RedundantStringCStrCheck.
366 if (!StringCStrCallExprMatcher) {
367 // Lazily create the matcher
368 const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
369 hasDeclaration(cxxRecordDecl(hasName("::std::basic_string"))))));
370 const auto StringExpr = expr(
371 anyOf(hasType(StringDecl), hasType(qualType(pointsTo(StringDecl)))));
373 StringCStrCallExprMatcher =
374 cxxMemberCallExpr(
375 on(StringExpr.bind("arg")), callee(memberExpr().bind("member")),
376 callee(cxxMethodDecl(hasAnyName("c_str", "data"),
377 returns(pointerType(pointee(isRealChar()))))))
378 .bind("call");
381 auto CStrMatches = match(*StringCStrCallExprMatcher, *Arg, *Context);
382 if (CStrMatches.size() == 1)
383 ArgCStrRemovals.push_back(CStrMatches.front());
384 else if (Arg->getType()->isPointerType()) {
385 const QualType Pointee = Arg->getType()->getPointeeType();
386 // printf is happy to print signed char and unsigned char strings, but
387 // std::format only likes char strings.
388 if (Pointee->isCharType() && !isRealCharType(Pointee))
389 ArgFixes.emplace_back(Arg, "reinterpret_cast<const char *>(");
393 bool FormatStringConverter::emitIntegerArgument(
394 ConversionSpecifier::Kind ArgKind, const Expr *Arg, unsigned ArgIndex,
395 std::string &FormatSpec) {
396 const clang::QualType &ArgType = Arg->getType();
397 if (ArgType->isBooleanType()) {
398 // std::format will print bool as either "true" or "false" by default,
399 // but printf prints them as "0" or "1". Be compatible with printf by
400 // requesting decimal output.
401 FormatSpec.push_back('d');
402 } else if (ArgType->isEnumeralType()) {
403 // std::format will try to find a specialization to print the enum
404 // (and probably fail), whereas printf would have just expected it to
405 // be passed as its underlying type. However, printf will have forced
406 // the signedness based on the format string, so we need to do the
407 // same.
408 if (const auto *ET = ArgType->getAs<EnumType>()) {
409 if (const std::optional<std::string> MaybeCastType =
410 castTypeForArgument(ArgKind, ET->getDecl()->getIntegerType()))
411 ArgFixes.emplace_back(
412 Arg, (Twine("static_cast<") + *MaybeCastType + ">(").str());
413 else
414 return conversionNotPossible(
415 (Twine("argument ") + Twine(ArgIndex) + " has unexpected enum type")
416 .str());
418 } else if (CastMismatchedIntegerTypes &&
419 !isMatchingSignedness(ArgKind, ArgType)) {
420 // printf will happily print an unsigned type as signed if told to.
421 // Even -Wformat doesn't warn for this. std::format will format as
422 // unsigned unless we cast it.
423 if (const std::optional<std::string> MaybeCastType =
424 castTypeForArgument(ArgKind, ArgType))
425 ArgFixes.emplace_back(
426 Arg, (Twine("static_cast<") + *MaybeCastType + ">(").str());
427 else
428 return conversionNotPossible(
429 (Twine("argument ") + Twine(ArgIndex) + " cannot be cast to " +
430 Twine(ArgKind == ConversionSpecifier::Kind::uArg ? "unsigned"
431 : "signed") +
432 " integer type to match format"
433 " specifier and StrictMode is enabled")
434 .str());
435 } else if (isRealCharType(ArgType) || !ArgType->isIntegerType()) {
436 // Only specify integer if the argument is of a different type
437 FormatSpec.push_back('d');
439 return true;
442 /// Append the corresponding standard format string type fragment to FormatSpec,
443 /// and store any argument fixes for later application.
444 /// @returns true on success, false on failure
445 bool FormatStringConverter::emitType(const PrintfSpecifier &FS, const Expr *Arg,
446 std::string &FormatSpec) {
447 ConversionSpecifier::Kind ArgKind = FS.getConversionSpecifier().getKind();
448 switch (ArgKind) {
449 case ConversionSpecifier::Kind::sArg:
450 emitStringArgument(Arg);
451 break;
452 case ConversionSpecifier::Kind::cArg:
453 // The type must be "c" to get a character unless the type is exactly
454 // char (whether that be signed or unsigned for the target.)
455 if (!isRealCharType(Arg->getType()))
456 FormatSpec.push_back('c');
457 break;
458 case ConversionSpecifier::Kind::dArg:
459 case ConversionSpecifier::Kind::iArg:
460 case ConversionSpecifier::Kind::uArg:
461 if (!emitIntegerArgument(ArgKind, Arg, FS.getArgIndex() + ArgsOffset,
462 FormatSpec))
463 return false;
464 break;
465 case ConversionSpecifier::Kind::pArg: {
466 const clang::QualType &ArgType = Arg->getType();
467 // std::format knows how to format void pointers and nullptrs
468 if (!ArgType->isNullPtrType() && !ArgType->isVoidPointerType())
469 ArgFixes.emplace_back(Arg, "static_cast<const void *>(");
470 break;
472 case ConversionSpecifier::Kind::xArg:
473 FormatSpec.push_back('x');
474 break;
475 case ConversionSpecifier::Kind::XArg:
476 FormatSpec.push_back('X');
477 break;
478 case ConversionSpecifier::Kind::oArg:
479 FormatSpec.push_back('o');
480 break;
481 case ConversionSpecifier::Kind::aArg:
482 FormatSpec.push_back('a');
483 break;
484 case ConversionSpecifier::Kind::AArg:
485 FormatSpec.push_back('A');
486 break;
487 case ConversionSpecifier::Kind::eArg:
488 FormatSpec.push_back('e');
489 break;
490 case ConversionSpecifier::Kind::EArg:
491 FormatSpec.push_back('E');
492 break;
493 case ConversionSpecifier::Kind::fArg:
494 FormatSpec.push_back('f');
495 break;
496 case ConversionSpecifier::Kind::FArg:
497 FormatSpec.push_back('F');
498 break;
499 case ConversionSpecifier::Kind::gArg:
500 FormatSpec.push_back('g');
501 break;
502 case ConversionSpecifier::Kind::GArg:
503 FormatSpec.push_back('G');
504 break;
505 default:
506 // Something we don't understand
507 return conversionNotPossible((Twine("argument ") +
508 Twine(FS.getArgIndex() + ArgsOffset) +
509 " has an unsupported format specifier")
510 .str());
513 return true;
516 /// Append the standard format string equivalent of the passed PrintfSpecifier
517 /// to StandardFormatString and store any argument fixes for later application.
518 /// @returns true on success, false on failure
519 bool FormatStringConverter::convertArgument(const PrintfSpecifier &FS,
520 const Expr *Arg,
521 std::string &StandardFormatString) {
522 // The specifier must have an associated argument
523 assert(FS.consumesDataArgument());
525 StandardFormatString.push_back('{');
527 if (FS.usesPositionalArg()) {
528 // std::format argument identifiers are zero-based, whereas printf ones
529 // are one based.
530 assert(FS.getPositionalArgIndex() > 0U);
531 StandardFormatString.append(llvm::utostr(FS.getPositionalArgIndex() - 1));
534 // std::format format argument parts to potentially emit:
535 // [[fill]align][sign]["#"]["0"][width]["."precision][type]
536 std::string FormatSpec;
538 // printf doesn't support specifying the fill character - it's always a
539 // space, so we never need to generate one.
541 emitAlignment(FS, FormatSpec);
542 emitSign(FS, FormatSpec);
543 emitAlternativeForm(FS, FormatSpec);
545 if (FS.hasLeadingZeros())
546 FormatSpec.push_back('0');
548 emitFieldWidth(FS, FormatSpec);
549 emitPrecision(FS, FormatSpec);
550 maybeRotateArguments(FS);
552 if (!emitType(FS, Arg, FormatSpec))
553 return false;
555 if (!FormatSpec.empty()) {
556 StandardFormatString.push_back(':');
557 StandardFormatString.append(FormatSpec);
560 StandardFormatString.push_back('}');
561 return true;
564 /// Called for each format specifier by ParsePrintfString.
565 bool FormatStringConverter::HandlePrintfSpecifier(const PrintfSpecifier &FS,
566 const char *StartSpecifier,
567 unsigned SpecifierLen,
568 const TargetInfo &Target) {
570 const size_t StartSpecifierPos = StartSpecifier - PrintfFormatString.data();
571 assert(StartSpecifierPos + SpecifierLen <= PrintfFormatString.size());
573 // Everything before the specifier needs copying verbatim
574 assert(StartSpecifierPos >= PrintfFormatStringPos);
576 appendFormatText(StringRef(PrintfFormatString.begin() + PrintfFormatStringPos,
577 StartSpecifierPos - PrintfFormatStringPos));
579 const ConversionSpecifier::Kind ArgKind =
580 FS.getConversionSpecifier().getKind();
582 // Skip over specifier
583 PrintfFormatStringPos = StartSpecifierPos + SpecifierLen;
584 assert(PrintfFormatStringPos <= PrintfFormatString.size());
586 FormatStringNeededRewriting = true;
588 if (ArgKind == ConversionSpecifier::Kind::nArg) {
589 // std::print doesn't do the equivalent of %n
590 return conversionNotPossible("'%n' is not supported in format string");
593 if (ArgKind == ConversionSpecifier::Kind::PrintErrno) {
594 // std::print doesn't support %m. In theory we could insert a
595 // strerror(errno) parameter (assuming that libc has a thread-safe
596 // implementation, which glibc does), but that would require keeping track
597 // of the input and output parameter indices for position arguments too.
598 return conversionNotPossible("'%m' is not supported in format string");
601 if (ArgKind == ConversionSpecifier::PercentArg) {
602 StandardFormatString.push_back('%');
603 return true;
606 const unsigned ArgIndex = FS.getArgIndex() + ArgsOffset;
607 if (ArgIndex >= NumArgs) {
608 // Argument index out of range. Give up.
609 return conversionNotPossible(
610 (Twine("argument index ") + Twine(ArgIndex) + " is out of range")
611 .str());
614 return convertArgument(FS, Args[ArgIndex]->IgnoreImplicitAsWritten(),
615 StandardFormatString);
618 /// Called at the very end just before applying fixes to capture the last part
619 /// of the format string.
620 void FormatStringConverter::finalizeFormatText() {
621 appendFormatText(
622 StringRef(PrintfFormatString.begin() + PrintfFormatStringPos,
623 PrintfFormatString.size() - PrintfFormatStringPos));
624 PrintfFormatStringPos = PrintfFormatString.size();
626 // It's clearer to convert printf("Hello\r\n"); to std::print("Hello\r\n")
627 // than to std::println("Hello\r");
628 if (StringRef(StandardFormatString).ends_with("\\n") &&
629 !StringRef(StandardFormatString).ends_with("\\\\n") &&
630 !StringRef(StandardFormatString).ends_with("\\r\\n")) {
631 UsePrintNewlineFunction = true;
632 FormatStringNeededRewriting = true;
633 StandardFormatString.erase(StandardFormatString.end() - 2,
634 StandardFormatString.end());
637 StandardFormatString.push_back('\"');
640 /// Append literal parts of the format text, reinstating escapes as required.
641 void FormatStringConverter::appendFormatText(const StringRef Text) {
642 for (const char Ch : Text) {
643 if (Ch == '\a')
644 StandardFormatString += "\\a";
645 else if (Ch == '\b')
646 StandardFormatString += "\\b";
647 else if (Ch == '\f')
648 StandardFormatString += "\\f";
649 else if (Ch == '\n')
650 StandardFormatString += "\\n";
651 else if (Ch == '\r')
652 StandardFormatString += "\\r";
653 else if (Ch == '\t')
654 StandardFormatString += "\\t";
655 else if (Ch == '\v')
656 StandardFormatString += "\\v";
657 else if (Ch == '\"')
658 StandardFormatString += "\\\"";
659 else if (Ch == '\\')
660 StandardFormatString += "\\\\";
661 else if (Ch == '{') {
662 StandardFormatString += "{{";
663 FormatStringNeededRewriting = true;
664 } else if (Ch == '}') {
665 StandardFormatString += "}}";
666 FormatStringNeededRewriting = true;
667 } else if (Ch < 32) {
668 StandardFormatString += "\\x";
669 StandardFormatString += llvm::hexdigit(Ch >> 4, true);
670 StandardFormatString += llvm::hexdigit(Ch & 0xf, true);
671 } else
672 StandardFormatString += Ch;
676 /// Called by the check when it is ready to apply the fixes.
677 void FormatStringConverter::applyFixes(DiagnosticBuilder &Diag,
678 SourceManager &SM) {
679 if (FormatStringNeededRewriting) {
680 Diag << FixItHint::CreateReplacement(
681 CharSourceRange::getTokenRange(FormatExpr->getBeginLoc(),
682 FormatExpr->getEndLoc()),
683 StandardFormatString);
686 for (const auto &[Arg, Replacement] : ArgFixes) {
687 SourceLocation AfterOtherSide =
688 Lexer::findNextToken(Arg->getEndLoc(), SM, LangOpts)->getLocation();
690 Diag << FixItHint::CreateInsertion(Arg->getBeginLoc(), Replacement)
691 << FixItHint::CreateInsertion(AfterOtherSide, ")");
694 for (const auto &Match : ArgCStrRemovals) {
695 const auto *Call = Match.getNodeAs<CallExpr>("call");
696 const auto *Arg = Match.getNodeAs<Expr>("arg");
697 const auto *Member = Match.getNodeAs<MemberExpr>("member");
698 const bool Arrow = Member->isArrow();
699 const std::string ArgText =
700 Arrow ? utils::fixit::formatDereference(*Arg, *Context)
701 : tooling::fixit::getText(*Arg, *Context).str();
702 if (!ArgText.empty())
703 Diag << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText);
706 // ArgCount is one less than the number of arguments to be rotated.
707 for (auto [ValueArgIndex, ArgCount] : ArgRotates) {
708 assert(ValueArgIndex < NumArgs);
709 assert(ValueArgIndex > ArgCount);
711 // First move the value argument to the right place.
712 Diag << tooling::fixit::createReplacement(*Args[ValueArgIndex - ArgCount],
713 *Args[ValueArgIndex], *Context);
715 // Now shift down the field width and precision (if either are present) to
716 // accommodate it.
717 for (size_t Offset = 0; Offset < ArgCount; ++Offset)
718 Diag << tooling::fixit::createReplacement(
719 *Args[ValueArgIndex - Offset], *Args[ValueArgIndex - Offset - 1],
720 *Context);
723 } // namespace clang::tidy::utils