1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
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 //===----------------------------------------------------------------------===//
9 // Handling of format string in printf and friends. The structure of format
10 // strings for fprintf() are described in C99 7.19.6.1.
12 //===----------------------------------------------------------------------===//
14 #include "FormatStringParsing.h"
15 #include "clang/AST/FormatString.h"
16 #include "clang/AST/OSLog.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "llvm/Support/Regex.h"
20 using clang::analyze_format_string::ArgType
;
21 using clang::analyze_format_string::FormatStringHandler
;
22 using clang::analyze_format_string::LengthModifier
;
23 using clang::analyze_format_string::OptionalAmount
;
24 using clang::analyze_format_string::ConversionSpecifier
;
25 using clang::analyze_printf::PrintfSpecifier
;
27 using namespace clang
;
29 typedef clang::analyze_format_string::SpecifierResult
<PrintfSpecifier
>
30 PrintfSpecifierResult
;
32 //===----------------------------------------------------------------------===//
33 // Methods for parsing format strings.
34 //===----------------------------------------------------------------------===//
36 using analyze_format_string::ParseNonPositionAmount
;
38 static bool ParsePrecision(FormatStringHandler
&H
, PrintfSpecifier
&FS
,
39 const char *Start
, const char *&Beg
, const char *E
,
42 FS
.setPrecision(ParseNonPositionAmount(Beg
, E
, *argIndex
));
44 const OptionalAmount Amt
= ParsePositionAmount(H
, Start
, Beg
, E
,
45 analyze_format_string::PrecisionPos
);
53 static bool ParseObjCFlags(FormatStringHandler
&H
, PrintfSpecifier
&FS
,
54 const char *FlagBeg
, const char *E
, bool Warn
) {
55 StringRef
Flag(FlagBeg
, E
- FlagBeg
);
56 // Currently there is only one flag.
58 FS
.setHasObjCTechnicalTerm(FlagBeg
);
61 // Handle either the case of no flag or an invalid flag.
64 H
.HandleEmptyObjCModifierFlag(FlagBeg
, E
- FlagBeg
);
66 H
.HandleInvalidObjCModifierFlag(FlagBeg
, E
- FlagBeg
);
71 static PrintfSpecifierResult
ParsePrintfSpecifier(FormatStringHandler
&H
,
75 const LangOptions
&LO
,
76 const TargetInfo
&Target
,
78 bool isFreeBSDKPrintf
) {
80 using namespace clang::analyze_format_string
;
81 using namespace clang::analyze_printf
;
84 const char *Start
= nullptr;
85 UpdateOnReturn
<const char*> UpdateBeg(Beg
, I
);
87 // Look for a '%' character that indicates the start of a format specifier.
88 for ( ; I
!= E
; ++I
) {
91 // Detect spurious null characters, which are likely errors.
96 Start
= I
++; // Record the start of the format specifier.
101 // No format specifier found?
106 // No more characters left?
108 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
113 if (ParseArgPosition(H
, FS
, Start
, I
, E
))
117 // No more characters left?
119 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
125 unsigned char PrivacyFlags
= 0;
126 StringRef MatchedStr
;
129 StringRef
Str(I
, E
- I
);
130 std::string Match
= "^[[:space:]]*"
131 "(private|public|sensitive|mask\\.[^[:space:],}]*)"
133 llvm::Regex
R(Match
);
134 SmallVector
<StringRef
, 2> Matches
;
136 if (R
.match(Str
, &Matches
)) {
137 MatchedStr
= Matches
[1];
138 I
+= Matches
[0].size();
140 // Set the privacy flag if the privacy annotation in the
141 // comma-delimited segment is at least as strict as the privacy
142 // annotations in previous comma-delimited segments.
143 if (MatchedStr
.startswith("mask")) {
144 StringRef MaskType
= MatchedStr
.substr(sizeof("mask.") - 1);
145 unsigned Size
= MaskType
.size();
146 if (Warn
&& (Size
== 0 || Size
> 8))
147 H
.handleInvalidMaskType(MaskType
);
148 FS
.setMaskType(MaskType
);
149 } else if (MatchedStr
.equals("sensitive"))
150 PrivacyFlags
= clang::analyze_os_log::OSLogBufferItem::IsSensitive
;
151 else if (PrivacyFlags
!=
152 clang::analyze_os_log::OSLogBufferItem::IsSensitive
&&
153 MatchedStr
.equals("private"))
154 PrivacyFlags
= clang::analyze_os_log::OSLogBufferItem::IsPrivate
;
155 else if (PrivacyFlags
== 0 && MatchedStr
.equals("public"))
156 PrivacyFlags
= clang::analyze_os_log::OSLogBufferItem::IsPublic
;
158 size_t CommaOrBracePos
=
159 Str
.find_if([](char c
) { return c
== ',' || c
== '}'; });
161 if (CommaOrBracePos
== StringRef::npos
) {
162 // Neither a comma nor the closing brace was found.
164 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
168 I
+= CommaOrBracePos
+ 1;
170 // Continue until the closing brace is found.
171 } while (*(I
- 1) == ',');
173 // Set the privacy flag.
174 switch (PrivacyFlags
) {
177 case clang::analyze_os_log::OSLogBufferItem::IsPrivate
:
178 FS
.setIsPrivate(MatchedStr
.data());
180 case clang::analyze_os_log::OSLogBufferItem::IsPublic
:
181 FS
.setIsPublic(MatchedStr
.data());
183 case clang::analyze_os_log::OSLogBufferItem::IsSensitive
:
184 FS
.setIsSensitive(MatchedStr
.data());
187 llvm_unreachable("Unexpected privacy flag value");
191 // Look for flags (if any).
193 for ( ; I
!= E
; ++I
) {
195 default: hasMore
= false; break;
197 // FIXME: POSIX specific. Always accept?
198 FS
.setHasThousandsGrouping(I
);
200 case '-': FS
.setIsLeftJustified(I
); break;
201 case '+': FS
.setHasPlusPrefix(I
); break;
202 case ' ': FS
.setHasSpacePrefix(I
); break;
203 case '#': FS
.setHasAlternativeForm(I
); break;
204 case '0': FS
.setHasLeadingZeros(I
); break;
211 // No more characters left?
213 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
217 // Look for the field width (if any).
218 if (ParseFieldWidth(H
, FS
, Start
, I
, E
,
219 FS
.usesPositionalArg() ? nullptr : &argIndex
))
223 // No more characters left?
225 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
229 // Look for the precision (if any).
234 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
238 if (ParsePrecision(H
, FS
, Start
, I
, E
,
239 FS
.usesPositionalArg() ? nullptr : &argIndex
))
243 // No more characters left?
245 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
250 if (ParseVectorModifier(H
, FS
, I
, E
, LO
))
253 // Look for the length modifier.
254 if (ParseLengthModifier(FS
, I
, E
, LO
) && I
== E
) {
255 // No more characters left?
257 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
261 // Look for the Objective-C modifier flags, if any.
262 // We parse these here, even if they don't apply to
263 // the conversion specifier, and then emit an error
264 // later if the conversion specifier isn't '@'. This
265 // enables better recovery, and we don't know if
266 // these flags are applicable until later.
267 const char *ObjCModifierFlagsStart
= nullptr,
268 *ObjCModifierFlagsEnd
= nullptr;
270 ObjCModifierFlagsStart
= I
;
274 ObjCModifierFlagsEnd
= I
;
277 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
280 // Did we find the closing ']'?
282 if (ParseObjCFlags(H
, FS
, flagStart
, I
, Warn
))
287 // There are no separators defined yet for multiple
288 // Objective-C modifier flags. When those are
289 // defined, this is the place to check.
294 // Detect spurious null characters, which are likely errors.
299 // Finally, look for the conversion specifier.
300 const char *conversionPosition
= I
++;
301 ConversionSpecifier::Kind k
= ConversionSpecifier::InvalidSpecifier
;
302 switch (*conversionPosition
) {
305 // C99: 7.19.6.1 (section 8).
306 case '%': k
= ConversionSpecifier::PercentArg
; break;
307 case 'A': k
= ConversionSpecifier::AArg
; break;
308 case 'E': k
= ConversionSpecifier::EArg
; break;
309 case 'F': k
= ConversionSpecifier::FArg
; break;
310 case 'G': k
= ConversionSpecifier::GArg
; break;
311 case 'X': k
= ConversionSpecifier::XArg
; break;
312 case 'a': k
= ConversionSpecifier::aArg
; break;
313 case 'c': k
= ConversionSpecifier::cArg
; break;
314 case 'd': k
= ConversionSpecifier::dArg
; break;
315 case 'e': k
= ConversionSpecifier::eArg
; break;
316 case 'f': k
= ConversionSpecifier::fArg
; break;
317 case 'g': k
= ConversionSpecifier::gArg
; break;
318 case 'i': k
= ConversionSpecifier::iArg
; break;
320 // Not handled, but reserved in OpenCL.
322 k
= ConversionSpecifier::nArg
;
324 case 'o': k
= ConversionSpecifier::oArg
; break;
325 case 'p': k
= ConversionSpecifier::pArg
; break;
326 case 's': k
= ConversionSpecifier::sArg
; break;
327 case 'u': k
= ConversionSpecifier::uArg
; break;
328 case 'x': k
= ConversionSpecifier::xArg
; break;
331 if (isFreeBSDKPrintf
)
332 k
= ConversionSpecifier::FreeBSDbArg
; // int followed by char *
334 k
= ConversionSpecifier::bArg
;
336 case 'B': k
= ConversionSpecifier::BArg
; break;
338 case 'C': k
= ConversionSpecifier::CArg
; break;
339 case 'S': k
= ConversionSpecifier::SArg
; break;
340 // Apple extension for os_log
342 k
= ConversionSpecifier::PArg
;
345 case '@': k
= ConversionSpecifier::ObjCObjArg
; break;
347 case 'm': k
= ConversionSpecifier::PrintErrno
; break;
349 if (isFreeBSDKPrintf
)
350 k
= ConversionSpecifier::FreeBSDrArg
; // int
353 if (isFreeBSDKPrintf
)
354 k
= ConversionSpecifier::FreeBSDyArg
; // int
358 if (isFreeBSDKPrintf
)
359 k
= ConversionSpecifier::FreeBSDDArg
; // void * followed by char *
360 else if (Target
.getTriple().isOSDarwin())
361 k
= ConversionSpecifier::DArg
;
364 if (Target
.getTriple().isOSDarwin())
365 k
= ConversionSpecifier::OArg
;
368 if (Target
.getTriple().isOSDarwin())
369 k
= ConversionSpecifier::UArg
;
373 if (Target
.getTriple().isOSMSVCRT())
374 k
= ConversionSpecifier::ZArg
;
378 // Check to see if we used the Objective-C modifier flags with
379 // a conversion specifier other than '@'.
380 if (k
!= ConversionSpecifier::ObjCObjArg
&&
381 k
!= ConversionSpecifier::InvalidSpecifier
&&
382 ObjCModifierFlagsStart
) {
383 H
.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart
,
384 ObjCModifierFlagsEnd
+ 1,
389 PrintfConversionSpecifier
CS(conversionPosition
, k
);
390 FS
.setConversionSpecifier(CS
);
391 if (CS
.consumesDataArgument() && !FS
.usesPositionalArg())
392 FS
.setArgIndex(argIndex
++);
393 // FreeBSD kernel specific.
394 if (k
== ConversionSpecifier::FreeBSDbArg
||
395 k
== ConversionSpecifier::FreeBSDDArg
)
398 if (k
== ConversionSpecifier::InvalidSpecifier
) {
399 unsigned Len
= I
- Start
;
400 if (ParseUTF8InvalidSpecifier(Start
, E
, Len
)) {
401 CS
.setEndScanList(Start
+ Len
);
402 FS
.setConversionSpecifier(CS
);
404 // Assume the conversion takes one argument.
405 return !H
.HandleInvalidPrintfConversionSpecifier(FS
, Start
, Len
);
407 return PrintfSpecifierResult(Start
, FS
);
410 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler
&H
,
413 const LangOptions
&LO
,
414 const TargetInfo
&Target
,
415 bool isFreeBSDKPrintf
) {
417 unsigned argIndex
= 0;
419 // Keep looking for a format specifier until we have exhausted the string.
421 const PrintfSpecifierResult
&FSR
= ParsePrintfSpecifier(H
, I
, E
, argIndex
,
424 // Did a fail-stop error of any kind occur when parsing the specifier?
425 // If so, don't do any more processing.
426 if (FSR
.shouldStop())
428 // Did we exhaust the string or encounter an error that
429 // we can recover from?
432 // We have a format specifier. Pass it to the callback.
433 if (!H
.HandlePrintfSpecifier(FSR
.getValue(), FSR
.getStart(),
434 I
- FSR
.getStart(), Target
))
437 assert(I
== E
&& "Format string not exhausted");
441 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I
,
443 const LangOptions
&LO
,
444 const TargetInfo
&Target
) {
446 unsigned argIndex
= 0;
448 // Keep looking for a %s format specifier until we have exhausted the string.
449 FormatStringHandler H
;
451 const PrintfSpecifierResult
&FSR
= ParsePrintfSpecifier(H
, I
, E
, argIndex
,
454 // Did a fail-stop error of any kind occur when parsing the specifier?
455 // If so, don't do any more processing.
456 if (FSR
.shouldStop())
458 // Did we exhaust the string or encounter an error that
459 // we can recover from?
462 const analyze_printf::PrintfSpecifier
&FS
= FSR
.getValue();
463 // Return true if this a %s format specifier.
464 if (FS
.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg
)
470 bool clang::analyze_format_string::parseFormatStringHasFormattingSpecifiers(
471 const char *Begin
, const char *End
, const LangOptions
&LO
,
472 const TargetInfo
&Target
) {
473 unsigned ArgIndex
= 0;
474 // Keep looking for a formatting specifier until we have exhausted the string.
475 FormatStringHandler H
;
476 while (Begin
!= End
) {
477 const PrintfSpecifierResult
&FSR
=
478 ParsePrintfSpecifier(H
, Begin
, End
, ArgIndex
, LO
, Target
, false, false);
479 if (FSR
.shouldStop())
487 //===----------------------------------------------------------------------===//
488 // Methods on PrintfSpecifier.
489 //===----------------------------------------------------------------------===//
491 ArgType
PrintfSpecifier::getScalarArgType(ASTContext
&Ctx
,
492 bool IsObjCLiteral
) const {
493 if (CS
.getKind() == ConversionSpecifier::cArg
)
494 switch (LM
.getKind()) {
495 case LengthModifier::None
:
497 case LengthModifier::AsLong
:
498 case LengthModifier::AsWide
:
499 return ArgType(ArgType::WIntTy
, "wint_t");
500 case LengthModifier::AsShort
:
501 if (Ctx
.getTargetInfo().getTriple().isOSMSVCRT())
505 return ArgType::Invalid();
509 switch (LM
.getKind()) {
510 case LengthModifier::AsLongDouble
:
512 return Ctx
.LongLongTy
;
513 case LengthModifier::None
:
514 case LengthModifier::AsShortLong
:
516 case LengthModifier::AsInt32
:
517 return ArgType(Ctx
.IntTy
, "__int32");
518 case LengthModifier::AsChar
:
519 return ArgType::AnyCharTy
;
520 case LengthModifier::AsShort
: return Ctx
.ShortTy
;
521 case LengthModifier::AsLong
: return Ctx
.LongTy
;
522 case LengthModifier::AsLongLong
:
523 case LengthModifier::AsQuad
:
524 return Ctx
.LongLongTy
;
525 case LengthModifier::AsInt64
:
526 return ArgType(Ctx
.LongLongTy
, "__int64");
527 case LengthModifier::AsIntMax
:
528 return ArgType(Ctx
.getIntMaxType(), "intmax_t");
529 case LengthModifier::AsSizeT
:
530 return ArgType::makeSizeT(ArgType(Ctx
.getSignedSizeType(), "ssize_t"));
531 case LengthModifier::AsInt3264
:
532 return Ctx
.getTargetInfo().getTriple().isArch64Bit()
533 ? ArgType(Ctx
.LongLongTy
, "__int64")
534 : ArgType(Ctx
.IntTy
, "__int32");
535 case LengthModifier::AsPtrDiff
:
536 return ArgType::makePtrdiffT(
537 ArgType(Ctx
.getPointerDiffType(), "ptrdiff_t"));
538 case LengthModifier::AsAllocate
:
539 case LengthModifier::AsMAllocate
:
540 case LengthModifier::AsWide
:
541 return ArgType::Invalid();
545 switch (LM
.getKind()) {
546 case LengthModifier::AsLongDouble
:
548 return Ctx
.UnsignedLongLongTy
;
549 case LengthModifier::None
:
550 case LengthModifier::AsShortLong
:
551 return Ctx
.UnsignedIntTy
;
552 case LengthModifier::AsInt32
:
553 return ArgType(Ctx
.UnsignedIntTy
, "unsigned __int32");
554 case LengthModifier::AsChar
: return Ctx
.UnsignedCharTy
;
555 case LengthModifier::AsShort
: return Ctx
.UnsignedShortTy
;
556 case LengthModifier::AsLong
: return Ctx
.UnsignedLongTy
;
557 case LengthModifier::AsLongLong
:
558 case LengthModifier::AsQuad
:
559 return Ctx
.UnsignedLongLongTy
;
560 case LengthModifier::AsInt64
:
561 return ArgType(Ctx
.UnsignedLongLongTy
, "unsigned __int64");
562 case LengthModifier::AsIntMax
:
563 return ArgType(Ctx
.getUIntMaxType(), "uintmax_t");
564 case LengthModifier::AsSizeT
:
565 return ArgType::makeSizeT(ArgType(Ctx
.getSizeType(), "size_t"));
566 case LengthModifier::AsInt3264
:
567 return Ctx
.getTargetInfo().getTriple().isArch64Bit()
568 ? ArgType(Ctx
.UnsignedLongLongTy
, "unsigned __int64")
569 : ArgType(Ctx
.UnsignedIntTy
, "unsigned __int32");
570 case LengthModifier::AsPtrDiff
:
571 return ArgType::makePtrdiffT(
572 ArgType(Ctx
.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
573 case LengthModifier::AsAllocate
:
574 case LengthModifier::AsMAllocate
:
575 case LengthModifier::AsWide
:
576 return ArgType::Invalid();
579 if (CS
.isDoubleArg()) {
580 if (!VectorNumElts
.isInvalid()) {
581 switch (LM
.getKind()) {
582 case LengthModifier::AsShort
:
584 case LengthModifier::AsShortLong
:
586 case LengthModifier::AsLong
:
592 if (LM
.getKind() == LengthModifier::AsLongDouble
)
593 return Ctx
.LongDoubleTy
;
597 if (CS
.getKind() == ConversionSpecifier::nArg
) {
598 switch (LM
.getKind()) {
599 case LengthModifier::None
:
600 return ArgType::PtrTo(Ctx
.IntTy
);
601 case LengthModifier::AsChar
:
602 return ArgType::PtrTo(Ctx
.SignedCharTy
);
603 case LengthModifier::AsShort
:
604 return ArgType::PtrTo(Ctx
.ShortTy
);
605 case LengthModifier::AsLong
:
606 return ArgType::PtrTo(Ctx
.LongTy
);
607 case LengthModifier::AsLongLong
:
608 case LengthModifier::AsQuad
:
609 return ArgType::PtrTo(Ctx
.LongLongTy
);
610 case LengthModifier::AsIntMax
:
611 return ArgType::PtrTo(ArgType(Ctx
.getIntMaxType(), "intmax_t"));
612 case LengthModifier::AsSizeT
:
613 return ArgType::PtrTo(ArgType(Ctx
.getSignedSizeType(), "ssize_t"));
614 case LengthModifier::AsPtrDiff
:
615 return ArgType::PtrTo(ArgType(Ctx
.getPointerDiffType(), "ptrdiff_t"));
616 case LengthModifier::AsLongDouble
:
617 return ArgType(); // FIXME: Is this a known extension?
618 case LengthModifier::AsAllocate
:
619 case LengthModifier::AsMAllocate
:
620 case LengthModifier::AsInt32
:
621 case LengthModifier::AsInt3264
:
622 case LengthModifier::AsInt64
:
623 case LengthModifier::AsWide
:
624 return ArgType::Invalid();
625 case LengthModifier::AsShortLong
:
626 llvm_unreachable("only used for OpenCL which doesn not handle nArg");
630 switch (CS
.getKind()) {
631 case ConversionSpecifier::sArg
:
632 if (LM
.getKind() == LengthModifier::AsWideChar
) {
634 return ArgType(Ctx
.getPointerType(Ctx
.UnsignedShortTy
.withConst()),
636 return ArgType(ArgType::WCStrTy
, "wchar_t *");
638 if (LM
.getKind() == LengthModifier::AsWide
)
639 return ArgType(ArgType::WCStrTy
, "wchar_t *");
640 return ArgType::CStrTy
;
641 case ConversionSpecifier::SArg
:
643 return ArgType(Ctx
.getPointerType(Ctx
.UnsignedShortTy
.withConst()),
645 if (Ctx
.getTargetInfo().getTriple().isOSMSVCRT() &&
646 LM
.getKind() == LengthModifier::AsShort
)
647 return ArgType::CStrTy
;
648 return ArgType(ArgType::WCStrTy
, "wchar_t *");
649 case ConversionSpecifier::CArg
:
651 return ArgType(Ctx
.UnsignedShortTy
, "unichar");
652 if (Ctx
.getTargetInfo().getTriple().isOSMSVCRT() &&
653 LM
.getKind() == LengthModifier::AsShort
)
655 return ArgType(Ctx
.WideCharTy
, "wchar_t");
656 case ConversionSpecifier::pArg
:
657 case ConversionSpecifier::PArg
:
658 return ArgType::CPointerTy
;
659 case ConversionSpecifier::ObjCObjArg
:
660 return ArgType::ObjCPointerTy
;
665 // FIXME: Handle other cases.
670 ArgType
PrintfSpecifier::getArgType(ASTContext
&Ctx
,
671 bool IsObjCLiteral
) const {
672 const PrintfConversionSpecifier
&CS
= getConversionSpecifier();
674 if (!CS
.consumesDataArgument())
675 return ArgType::Invalid();
677 ArgType ScalarTy
= getScalarArgType(Ctx
, IsObjCLiteral
);
678 if (!ScalarTy
.isValid() || VectorNumElts
.isInvalid())
681 return ScalarTy
.makeVectorType(Ctx
, VectorNumElts
.getConstantAmount());
684 bool PrintfSpecifier::fixType(QualType QT
, const LangOptions
&LangOpt
,
685 ASTContext
&Ctx
, bool IsObjCLiteral
) {
686 // %n is different from other conversion specifiers; don't try to fix it.
687 if (CS
.getKind() == ConversionSpecifier::nArg
)
690 // Handle Objective-C objects first. Note that while the '%@' specifier will
691 // not warn for structure pointer or void pointer arguments (because that's
692 // how CoreFoundation objects are implemented), we only show a fixit for '%@'
693 // if we know it's an object (block, id, class, or __attribute__((NSObject))).
694 if (QT
->isObjCRetainableType()) {
698 CS
.setKind(ConversionSpecifier::ObjCObjArg
);
700 // Disable irrelevant flags
701 HasThousandsGrouping
= false;
702 HasPlusPrefix
= false;
703 HasSpacePrefix
= false;
704 HasAlternativeForm
= false;
705 HasLeadingZeroes
= false;
706 Precision
.setHowSpecified(OptionalAmount::NotSpecified
);
707 LM
.setKind(LengthModifier::None
);
712 // Handle strings next (char *, wchar_t *)
713 if (QT
->isPointerType() && (QT
->getPointeeType()->isAnyCharacterType())) {
714 CS
.setKind(ConversionSpecifier::sArg
);
716 // Disable irrelevant flags
717 HasAlternativeForm
= false;
718 HasLeadingZeroes
= false;
720 // Set the long length modifier for wide characters
721 if (QT
->getPointeeType()->isWideCharType())
722 LM
.setKind(LengthModifier::AsWideChar
);
724 LM
.setKind(LengthModifier::None
);
729 // If it's an enum, get its underlying type.
730 if (const EnumType
*ETy
= QT
->getAs
<EnumType
>())
731 QT
= ETy
->getDecl()->getIntegerType();
733 const BuiltinType
*BT
= QT
->getAs
<BuiltinType
>();
735 const VectorType
*VT
= QT
->getAs
<VectorType
>();
737 QT
= VT
->getElementType();
738 BT
= QT
->getAs
<BuiltinType
>();
739 VectorNumElts
= OptionalAmount(VT
->getNumElements());
743 // We can only work with builtin types.
747 // Set length modifier
748 switch (BT
->getKind()) {
749 case BuiltinType::Bool
:
750 case BuiltinType::WChar_U
:
751 case BuiltinType::WChar_S
:
752 case BuiltinType::Char8
: // FIXME: Treat like 'char'?
753 case BuiltinType::Char16
:
754 case BuiltinType::Char32
:
755 case BuiltinType::UInt128
:
756 case BuiltinType::Int128
:
757 case BuiltinType::Half
:
758 case BuiltinType::BFloat16
:
759 case BuiltinType::Float16
:
760 case BuiltinType::Float128
:
761 case BuiltinType::Ibm128
:
762 case BuiltinType::ShortAccum
:
763 case BuiltinType::Accum
:
764 case BuiltinType::LongAccum
:
765 case BuiltinType::UShortAccum
:
766 case BuiltinType::UAccum
:
767 case BuiltinType::ULongAccum
:
768 case BuiltinType::ShortFract
:
769 case BuiltinType::Fract
:
770 case BuiltinType::LongFract
:
771 case BuiltinType::UShortFract
:
772 case BuiltinType::UFract
:
773 case BuiltinType::ULongFract
:
774 case BuiltinType::SatShortAccum
:
775 case BuiltinType::SatAccum
:
776 case BuiltinType::SatLongAccum
:
777 case BuiltinType::SatUShortAccum
:
778 case BuiltinType::SatUAccum
:
779 case BuiltinType::SatULongAccum
:
780 case BuiltinType::SatShortFract
:
781 case BuiltinType::SatFract
:
782 case BuiltinType::SatLongFract
:
783 case BuiltinType::SatUShortFract
:
784 case BuiltinType::SatUFract
:
785 case BuiltinType::SatULongFract
:
786 // Various types which are non-trivial to correct.
789 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
790 case BuiltinType::Id:
791 #include "clang/Basic/OpenCLImageTypes.def"
792 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
793 case BuiltinType::Id:
794 #include "clang/Basic/OpenCLExtensionTypes.def"
795 #define SVE_TYPE(Name, Id, SingletonId) \
796 case BuiltinType::Id:
797 #include "clang/Basic/AArch64SVEACLETypes.def"
798 #define PPC_VECTOR_TYPE(Name, Id, Size) \
799 case BuiltinType::Id:
800 #include "clang/Basic/PPCTypes.def"
801 #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
802 #include "clang/Basic/RISCVVTypes.def"
803 #define SIGNED_TYPE(Id, SingletonId)
804 #define UNSIGNED_TYPE(Id, SingletonId)
805 #define FLOATING_TYPE(Id, SingletonId)
806 #define BUILTIN_TYPE(Id, SingletonId) \
807 case BuiltinType::Id:
808 #include "clang/AST/BuiltinTypes.def"
809 // Misc other stuff which doesn't make sense here.
812 case BuiltinType::UInt
:
813 case BuiltinType::Int
:
814 case BuiltinType::Float
:
815 LM
.setKind(VectorNumElts
.isInvalid() ?
816 LengthModifier::None
: LengthModifier::AsShortLong
);
818 case BuiltinType::Double
:
819 LM
.setKind(VectorNumElts
.isInvalid() ?
820 LengthModifier::None
: LengthModifier::AsLong
);
822 case BuiltinType::Char_U
:
823 case BuiltinType::UChar
:
824 case BuiltinType::Char_S
:
825 case BuiltinType::SChar
:
826 LM
.setKind(LengthModifier::AsChar
);
829 case BuiltinType::Short
:
830 case BuiltinType::UShort
:
831 LM
.setKind(LengthModifier::AsShort
);
834 case BuiltinType::Long
:
835 case BuiltinType::ULong
:
836 LM
.setKind(LengthModifier::AsLong
);
839 case BuiltinType::LongLong
:
840 case BuiltinType::ULongLong
:
841 LM
.setKind(LengthModifier::AsLongLong
);
844 case BuiltinType::LongDouble
:
845 LM
.setKind(LengthModifier::AsLongDouble
);
849 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
850 if (LangOpt
.C99
|| LangOpt
.CPlusPlus11
)
851 namedTypeToLengthModifier(QT
, LM
);
853 // If fixing the length modifier was enough, we might be done.
854 if (hasValidLengthModifier(Ctx
.getTargetInfo(), LangOpt
)) {
855 // If we're going to offer a fix anyway, make sure the sign matches.
856 switch (CS
.getKind()) {
857 case ConversionSpecifier::uArg
:
858 case ConversionSpecifier::UArg
:
859 if (QT
->isSignedIntegerType())
860 CS
.setKind(clang::analyze_format_string::ConversionSpecifier::dArg
);
862 case ConversionSpecifier::dArg
:
863 case ConversionSpecifier::DArg
:
864 case ConversionSpecifier::iArg
:
865 if (QT
->isUnsignedIntegerType() && !HasPlusPrefix
)
866 CS
.setKind(clang::analyze_format_string::ConversionSpecifier::uArg
);
869 // Other specifiers do not have signed/unsigned variants.
873 const analyze_printf::ArgType
&ATR
= getArgType(Ctx
, IsObjCLiteral
);
874 if (ATR
.isValid() && ATR
.matchesType(Ctx
, QT
))
878 // Set conversion specifier and disable any flags which do not apply to it.
879 // Let typedefs to char fall through to int, as %c is silly for uint8_t.
880 if (!QT
->getAs
<TypedefType
>() && QT
->isCharType()) {
881 CS
.setKind(ConversionSpecifier::cArg
);
882 LM
.setKind(LengthModifier::None
);
883 Precision
.setHowSpecified(OptionalAmount::NotSpecified
);
884 HasAlternativeForm
= false;
885 HasLeadingZeroes
= false;
886 HasPlusPrefix
= false;
888 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
889 else if (QT
->isRealFloatingType()) {
890 CS
.setKind(ConversionSpecifier::fArg
);
891 } else if (QT
->isSignedIntegerType()) {
892 CS
.setKind(ConversionSpecifier::dArg
);
893 HasAlternativeForm
= false;
894 } else if (QT
->isUnsignedIntegerType()) {
895 CS
.setKind(ConversionSpecifier::uArg
);
896 HasAlternativeForm
= false;
897 HasPlusPrefix
= false;
899 llvm_unreachable("Unexpected type");
905 void PrintfSpecifier::toString(raw_ostream
&os
) const {
906 // Whilst some features have no defined order, we are using the order
907 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
911 if (usesPositionalArg()) {
912 os
<< getPositionalArgIndex() << "$";
916 if (IsLeftJustified
) os
<< "-";
917 if (HasPlusPrefix
) os
<< "+";
918 if (HasSpacePrefix
) os
<< " ";
919 if (HasAlternativeForm
) os
<< "#";
920 if (HasLeadingZeroes
) os
<< "0";
922 // Minimum field width
923 FieldWidth
.toString(os
);
925 Precision
.toString(os
);
928 if (!VectorNumElts
.isInvalid())
929 os
<< 'v' << VectorNumElts
.getConstantAmount();
933 // Conversion specifier
937 bool PrintfSpecifier::hasValidPlusPrefix() const {
941 // The plus prefix only makes sense for signed conversions
942 switch (CS
.getKind()) {
943 case ConversionSpecifier::dArg
:
944 case ConversionSpecifier::DArg
:
945 case ConversionSpecifier::iArg
:
946 case ConversionSpecifier::fArg
:
947 case ConversionSpecifier::FArg
:
948 case ConversionSpecifier::eArg
:
949 case ConversionSpecifier::EArg
:
950 case ConversionSpecifier::gArg
:
951 case ConversionSpecifier::GArg
:
952 case ConversionSpecifier::aArg
:
953 case ConversionSpecifier::AArg
:
954 case ConversionSpecifier::FreeBSDrArg
:
955 case ConversionSpecifier::FreeBSDyArg
:
963 bool PrintfSpecifier::hasValidAlternativeForm() const {
964 if (!HasAlternativeForm
)
967 // Alternate form flag only valid with the bBoxXaAeEfFgG conversions
968 switch (CS
.getKind()) {
969 case ConversionSpecifier::bArg
:
970 case ConversionSpecifier::BArg
:
971 case ConversionSpecifier::oArg
:
972 case ConversionSpecifier::OArg
:
973 case ConversionSpecifier::xArg
:
974 case ConversionSpecifier::XArg
:
975 case ConversionSpecifier::aArg
:
976 case ConversionSpecifier::AArg
:
977 case ConversionSpecifier::eArg
:
978 case ConversionSpecifier::EArg
:
979 case ConversionSpecifier::fArg
:
980 case ConversionSpecifier::FArg
:
981 case ConversionSpecifier::gArg
:
982 case ConversionSpecifier::GArg
:
983 case ConversionSpecifier::FreeBSDrArg
:
984 case ConversionSpecifier::FreeBSDyArg
:
992 bool PrintfSpecifier::hasValidLeadingZeros() const {
993 if (!HasLeadingZeroes
)
996 // Leading zeroes flag only valid with the bBdiouxXaAeEfFgG conversions
997 switch (CS
.getKind()) {
998 case ConversionSpecifier::bArg
:
999 case ConversionSpecifier::BArg
:
1000 case ConversionSpecifier::dArg
:
1001 case ConversionSpecifier::DArg
:
1002 case ConversionSpecifier::iArg
:
1003 case ConversionSpecifier::oArg
:
1004 case ConversionSpecifier::OArg
:
1005 case ConversionSpecifier::uArg
:
1006 case ConversionSpecifier::UArg
:
1007 case ConversionSpecifier::xArg
:
1008 case ConversionSpecifier::XArg
:
1009 case ConversionSpecifier::aArg
:
1010 case ConversionSpecifier::AArg
:
1011 case ConversionSpecifier::eArg
:
1012 case ConversionSpecifier::EArg
:
1013 case ConversionSpecifier::fArg
:
1014 case ConversionSpecifier::FArg
:
1015 case ConversionSpecifier::gArg
:
1016 case ConversionSpecifier::GArg
:
1017 case ConversionSpecifier::FreeBSDrArg
:
1018 case ConversionSpecifier::FreeBSDyArg
:
1026 bool PrintfSpecifier::hasValidSpacePrefix() const {
1027 if (!HasSpacePrefix
)
1030 // The space prefix only makes sense for signed conversions
1031 switch (CS
.getKind()) {
1032 case ConversionSpecifier::dArg
:
1033 case ConversionSpecifier::DArg
:
1034 case ConversionSpecifier::iArg
:
1035 case ConversionSpecifier::fArg
:
1036 case ConversionSpecifier::FArg
:
1037 case ConversionSpecifier::eArg
:
1038 case ConversionSpecifier::EArg
:
1039 case ConversionSpecifier::gArg
:
1040 case ConversionSpecifier::GArg
:
1041 case ConversionSpecifier::aArg
:
1042 case ConversionSpecifier::AArg
:
1043 case ConversionSpecifier::FreeBSDrArg
:
1044 case ConversionSpecifier::FreeBSDyArg
:
1052 bool PrintfSpecifier::hasValidLeftJustified() const {
1053 if (!IsLeftJustified
)
1056 // The left justified flag is valid for all conversions except n
1057 switch (CS
.getKind()) {
1058 case ConversionSpecifier::nArg
:
1066 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
1067 if (!HasThousandsGrouping
)
1070 switch (CS
.getKind()) {
1071 case ConversionSpecifier::dArg
:
1072 case ConversionSpecifier::DArg
:
1073 case ConversionSpecifier::iArg
:
1074 case ConversionSpecifier::uArg
:
1075 case ConversionSpecifier::UArg
:
1076 case ConversionSpecifier::fArg
:
1077 case ConversionSpecifier::FArg
:
1078 case ConversionSpecifier::gArg
:
1079 case ConversionSpecifier::GArg
:
1086 bool PrintfSpecifier::hasValidPrecision() const {
1087 if (Precision
.getHowSpecified() == OptionalAmount::NotSpecified
)
1090 // Precision is only valid with the bBdiouxXaAeEfFgGsP conversions
1091 switch (CS
.getKind()) {
1092 case ConversionSpecifier::bArg
:
1093 case ConversionSpecifier::BArg
:
1094 case ConversionSpecifier::dArg
:
1095 case ConversionSpecifier::DArg
:
1096 case ConversionSpecifier::iArg
:
1097 case ConversionSpecifier::oArg
:
1098 case ConversionSpecifier::OArg
:
1099 case ConversionSpecifier::uArg
:
1100 case ConversionSpecifier::UArg
:
1101 case ConversionSpecifier::xArg
:
1102 case ConversionSpecifier::XArg
:
1103 case ConversionSpecifier::aArg
:
1104 case ConversionSpecifier::AArg
:
1105 case ConversionSpecifier::eArg
:
1106 case ConversionSpecifier::EArg
:
1107 case ConversionSpecifier::fArg
:
1108 case ConversionSpecifier::FArg
:
1109 case ConversionSpecifier::gArg
:
1110 case ConversionSpecifier::GArg
:
1111 case ConversionSpecifier::sArg
:
1112 case ConversionSpecifier::FreeBSDrArg
:
1113 case ConversionSpecifier::FreeBSDyArg
:
1114 case ConversionSpecifier::PArg
:
1121 bool PrintfSpecifier::hasValidFieldWidth() const {
1122 if (FieldWidth
.getHowSpecified() == OptionalAmount::NotSpecified
)
1125 // The field width is valid for all conversions except n
1126 switch (CS
.getKind()) {
1127 case ConversionSpecifier::nArg
: