1 //===--- FormatStringConverter.cpp - clang-tidy----------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 /// Implementation of the FormatStringConverter class which is used to convert
11 /// printf format strings to C++ std::formatter format strings.
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
);
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
:
56 case BuiltinType::UShort
:
57 case BuiltinType::Short
:
59 case BuiltinType::UInt
:
60 case BuiltinType::Int
:
62 case BuiltinType::ULong
:
63 case BuiltinType::Long
:
65 case BuiltinType::ULongLong
:
66 case BuiltinType::LongLong
:
69 llvm::dbgs() << "Unknown corresponding signed type for BuiltinType '"
70 << QT
.getAsString() << "'\n";
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";
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";
121 llvm::dbgs() << "Unknown corresponding unsigned type for BuiltinType '"
122 << UQT
.getAsString() << "'\n";
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";
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
)
167 if (ArgKind
== ConversionSpecifier::Kind::uArg
)
168 return ArgType
->isUnsignedIntegerType();
169 return ArgType
->isSignedIntegerType();
173 AST_MATCHER(clang::QualType
, isRealChar
) {
174 return clang::tidy::utils::isRealCharType(Node
);
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
191 const FunctionDecl
*FuncDecl
= Call
->getDirectCallee();
193 return FuncDecl
->isVariadic();
198 FormatStringConverter::FormatStringConverter(ASTContext
*ContextIn
,
199 const CallExpr
*Call
,
200 unsigned FormatArgOffset
,
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());
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('>');
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('#');
284 // Alternative forms don't exist for other argument kinds
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
:
297 case OptionalAmount::Constant
:
298 FormatSpec
.append(llvm::utostr(FieldWidth
.getConstantAmount()));
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('}');
310 case OptionalAmount::Invalid
:
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
:
322 case OptionalAmount::Constant
:
323 FormatSpec
.push_back('.');
324 FormatSpec
.append(llvm::utostr(FieldPrecision
.getConstantAmount()));
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);
334 llvm::utostr(FieldPrecision
.getPositionalArgIndex() - 1));
336 FormatSpec
.push_back('}');
338 case OptionalAmount::Invalid
:
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())
351 if (FieldPrecision
.getHowSpecified() == OptionalAmount::Arg
&&
352 !FieldPrecision
.usesPositionalArg())
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
=
375 on(StringExpr
.bind("arg")), callee(memberExpr().bind("member")),
376 callee(cxxMethodDecl(hasAnyName("c_str", "data"),
377 returns(pointerType(pointee(isRealChar()))))))
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
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());
414 return conversionNotPossible(
415 (Twine("argument ") + Twine(ArgIndex
) + " has unexpected enum type")
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());
428 return conversionNotPossible(
429 (Twine("argument ") + Twine(ArgIndex
) + " cannot be cast to " +
430 Twine(ArgKind
== ConversionSpecifier::Kind::uArg
? "unsigned"
432 " integer type to match format"
433 " specifier and StrictMode is enabled")
435 } else if (isRealCharType(ArgType
) || !ArgType
->isIntegerType()) {
436 // Only specify integer if the argument is of a different type
437 FormatSpec
.push_back('d');
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();
449 case ConversionSpecifier::Kind::sArg
:
450 emitStringArgument(Arg
);
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');
458 case ConversionSpecifier::Kind::dArg
:
459 case ConversionSpecifier::Kind::iArg
:
460 case ConversionSpecifier::Kind::uArg
:
461 if (!emitIntegerArgument(ArgKind
, Arg
, FS
.getArgIndex() + ArgsOffset
,
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 *>(");
472 case ConversionSpecifier::Kind::xArg
:
473 FormatSpec
.push_back('x');
475 case ConversionSpecifier::Kind::XArg
:
476 FormatSpec
.push_back('X');
478 case ConversionSpecifier::Kind::oArg
:
479 FormatSpec
.push_back('o');
481 case ConversionSpecifier::Kind::aArg
:
482 FormatSpec
.push_back('a');
484 case ConversionSpecifier::Kind::AArg
:
485 FormatSpec
.push_back('A');
487 case ConversionSpecifier::Kind::eArg
:
488 FormatSpec
.push_back('e');
490 case ConversionSpecifier::Kind::EArg
:
491 FormatSpec
.push_back('E');
493 case ConversionSpecifier::Kind::fArg
:
494 FormatSpec
.push_back('f');
496 case ConversionSpecifier::Kind::FArg
:
497 FormatSpec
.push_back('F');
499 case ConversionSpecifier::Kind::gArg
:
500 FormatSpec
.push_back('g');
502 case ConversionSpecifier::Kind::GArg
:
503 FormatSpec
.push_back('G');
506 // Something we don't understand
507 return conversionNotPossible((Twine("argument ") +
508 Twine(FS
.getArgIndex() + ArgsOffset
) +
509 " has an unsupported format specifier")
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
,
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
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
))
555 if (!FormatSpec
.empty()) {
556 StandardFormatString
.push_back(':');
557 StandardFormatString
.append(FormatSpec
);
560 StandardFormatString
.push_back('}');
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('%');
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")
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() {
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
) {
644 StandardFormatString
+= "\\a";
646 StandardFormatString
+= "\\b";
648 StandardFormatString
+= "\\f";
650 StandardFormatString
+= "\\n";
652 StandardFormatString
+= "\\r";
654 StandardFormatString
+= "\\t";
656 StandardFormatString
+= "\\v";
658 StandardFormatString
+= "\\\"";
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);
672 StandardFormatString
+= Ch
;
676 /// Called by the check when it is ready to apply the fixes.
677 void FormatStringConverter::applyFixes(DiagnosticBuilder
&Diag
,
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
717 for (size_t Offset
= 0; Offset
< ArgCount
; ++Offset
)
718 Diag
<< tooling::fixit::createReplacement(
719 *Args
[ValueArgIndex
- Offset
], *Args
[ValueArgIndex
- Offset
- 1],
723 } // namespace clang::tidy::utils