1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Handling of format string in printf and friends. The structure of format
11 // strings for fprintf() are described in C99 7.19.6.1.
13 //===----------------------------------------------------------------------===//
15 #include "clang/Analysis/Analyses/FormatString.h"
16 #include "FormatStringParsing.h"
17 #include "clang/Basic/TargetInfo.h"
19 using clang::analyze_format_string::ArgType;
20 using clang::analyze_format_string::FormatStringHandler;
21 using clang::analyze_format_string::LengthModifier;
22 using clang::analyze_format_string::OptionalAmount;
23 using clang::analyze_format_string::ConversionSpecifier;
24 using clang::analyze_printf::PrintfSpecifier;
26 using namespace clang;
28 typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
29 PrintfSpecifierResult;
31 //===----------------------------------------------------------------------===//
32 // Methods for parsing format strings.
33 //===----------------------------------------------------------------------===//
35 using analyze_format_string::ParseNonPositionAmount;
37 static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
38 const char *Start, const char *&Beg, const char *E,
41 FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
43 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
44 analyze_format_string::PrecisionPos);
52 static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS,
53 const char *FlagBeg, const char *E, bool Warn) {
54 StringRef Flag(FlagBeg, E - FlagBeg);
55 // Currently there is only one flag.
57 FS.setHasObjCTechnicalTerm(FlagBeg);
60 // Handle either the case of no flag or an invalid flag.
63 H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg);
65 H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg);
70 static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
74 const LangOptions &LO,
75 const TargetInfo &Target,
77 bool isFreeBSDKPrintf) {
79 using namespace clang::analyze_format_string;
80 using namespace clang::analyze_printf;
83 const char *Start = nullptr;
84 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
86 // Look for a '%' character that indicates the start of a format specifier.
87 for ( ; I != E ; ++I) {
90 // Detect spurious null characters, which are likely errors.
95 Start = I++; // Record the start of the format specifier.
100 // No format specifier found?
105 // No more characters left?
107 H.HandleIncompleteSpecifier(Start, E - Start);
112 if (ParseArgPosition(H, FS, Start, I, E))
116 // No more characters left?
118 H.HandleIncompleteSpecifier(Start, E - Start);
122 // Look for flags (if any).
124 for ( ; I != E; ++I) {
126 default: hasMore = false; break;
128 // FIXME: POSIX specific. Always accept?
129 FS.setHasThousandsGrouping(I);
131 case '-': FS.setIsLeftJustified(I); break;
132 case '+': FS.setHasPlusPrefix(I); break;
133 case ' ': FS.setHasSpacePrefix(I); break;
134 case '#': FS.setHasAlternativeForm(I); break;
135 case '0': FS.setHasLeadingZeros(I); break;
142 // No more characters left?
144 H.HandleIncompleteSpecifier(Start, E - Start);
148 // Look for the field width (if any).
149 if (ParseFieldWidth(H, FS, Start, I, E,
150 FS.usesPositionalArg() ? nullptr : &argIndex))
154 // No more characters left?
156 H.HandleIncompleteSpecifier(Start, E - Start);
160 // Look for the precision (if any).
165 H.HandleIncompleteSpecifier(Start, E - Start);
169 if (ParsePrecision(H, FS, Start, I, E,
170 FS.usesPositionalArg() ? nullptr : &argIndex))
174 // No more characters left?
176 H.HandleIncompleteSpecifier(Start, E - Start);
181 // Look for the length modifier.
182 if (ParseLengthModifier(FS, I, E, LO) && I == E) {
183 // No more characters left?
185 H.HandleIncompleteSpecifier(Start, E - Start);
189 // Look for the Objective-C modifier flags, if any.
190 // We parse these here, even if they don't apply to
191 // the conversion specifier, and then emit an error
192 // later if the conversion specifier isn't '@'. This
193 // enables better recovery, and we don't know if
194 // these flags are applicable until later.
195 const char *ObjCModifierFlagsStart = nullptr,
196 *ObjCModifierFlagsEnd = nullptr;
198 ObjCModifierFlagsStart = I;
202 ObjCModifierFlagsEnd = I;
205 H.HandleIncompleteSpecifier(Start, E - Start);
208 // Did we find the closing ']'?
210 if (ParseObjCFlags(H, FS, flagStart, I, Warn))
215 // There are no separators defined yet for multiple
216 // Objective-C modifier flags. When those are
217 // defined, this is the place to check.
222 // Detect spurious null characters, which are likely errors.
227 // Finally, look for the conversion specifier.
228 const char *conversionPosition = I++;
229 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
230 switch (*conversionPosition) {
233 // C99: 7.19.6.1 (section 8).
234 case '%': k = ConversionSpecifier::PercentArg; break;
235 case 'A': k = ConversionSpecifier::AArg; break;
236 case 'E': k = ConversionSpecifier::EArg; break;
237 case 'F': k = ConversionSpecifier::FArg; break;
238 case 'G': k = ConversionSpecifier::GArg; break;
239 case 'X': k = ConversionSpecifier::XArg; break;
240 case 'a': k = ConversionSpecifier::aArg; break;
241 case 'c': k = ConversionSpecifier::cArg; break;
242 case 'd': k = ConversionSpecifier::dArg; break;
243 case 'e': k = ConversionSpecifier::eArg; break;
244 case 'f': k = ConversionSpecifier::fArg; break;
245 case 'g': k = ConversionSpecifier::gArg; break;
246 case 'i': k = ConversionSpecifier::iArg; break;
247 case 'n': k = ConversionSpecifier::nArg; break;
248 case 'o': k = ConversionSpecifier::oArg; break;
249 case 'p': k = ConversionSpecifier::pArg; break;
250 case 's': k = ConversionSpecifier::sArg; break;
251 case 'u': k = ConversionSpecifier::uArg; break;
252 case 'x': k = ConversionSpecifier::xArg; break;
254 case 'C': k = ConversionSpecifier::CArg; break;
255 case 'S': k = ConversionSpecifier::SArg; break;
257 case '@': k = ConversionSpecifier::ObjCObjArg; break;
259 case 'm': k = ConversionSpecifier::PrintErrno; break;
260 // FreeBSD kernel specific.
262 if (isFreeBSDKPrintf)
263 k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
266 if (isFreeBSDKPrintf)
267 k = ConversionSpecifier::FreeBSDrArg; // int
270 if (isFreeBSDKPrintf)
271 k = ConversionSpecifier::FreeBSDyArg; // int
275 if (isFreeBSDKPrintf)
276 k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
277 else if (Target.getTriple().isOSDarwin())
278 k = ConversionSpecifier::DArg;
281 if (Target.getTriple().isOSDarwin())
282 k = ConversionSpecifier::OArg;
285 if (Target.getTriple().isOSDarwin())
286 k = ConversionSpecifier::UArg;
290 if (Target.getTriple().isOSMSVCRT())
291 k = ConversionSpecifier::ZArg;
294 // Check to see if we used the Objective-C modifier flags with
295 // a conversion specifier other than '@'.
296 if (k != ConversionSpecifier::ObjCObjArg &&
297 k != ConversionSpecifier::InvalidSpecifier &&
298 ObjCModifierFlagsStart) {
299 H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
300 ObjCModifierFlagsEnd + 1,
305 PrintfConversionSpecifier CS(conversionPosition, k);
306 FS.setConversionSpecifier(CS);
307 if (CS.consumesDataArgument() && !FS.usesPositionalArg())
308 FS.setArgIndex(argIndex++);
309 // FreeBSD kernel specific.
310 if (k == ConversionSpecifier::FreeBSDbArg ||
311 k == ConversionSpecifier::FreeBSDDArg)
314 if (k == ConversionSpecifier::InvalidSpecifier) {
315 // Assume the conversion takes one argument.
316 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
318 return PrintfSpecifierResult(Start, FS);
321 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
324 const LangOptions &LO,
325 const TargetInfo &Target,
326 bool isFreeBSDKPrintf) {
328 unsigned argIndex = 0;
330 // Keep looking for a format specifier until we have exhausted the string.
332 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
335 // Did a fail-stop error of any kind occur when parsing the specifier?
336 // If so, don't do any more processing.
337 if (FSR.shouldStop())
339 // Did we exhaust the string or encounter an error that
340 // we can recover from?
343 // We have a format specifier. Pass it to the callback.
344 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
348 assert(I == E && "Format string not exhausted");
352 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
354 const LangOptions &LO,
355 const TargetInfo &Target) {
357 unsigned argIndex = 0;
359 // Keep looking for a %s format specifier until we have exhausted the string.
360 FormatStringHandler H;
362 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
365 // Did a fail-stop error of any kind occur when parsing the specifier?
366 // If so, don't do any more processing.
367 if (FSR.shouldStop())
369 // Did we exhaust the string or encounter an error that
370 // we can recover from?
373 const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
374 // Return true if this a %s format specifier.
375 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
381 //===----------------------------------------------------------------------===//
382 // Methods on PrintfSpecifier.
383 //===----------------------------------------------------------------------===//
385 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
386 bool IsObjCLiteral) const {
387 const PrintfConversionSpecifier &CS = getConversionSpecifier();
389 if (!CS.consumesDataArgument())
390 return ArgType::Invalid();
392 if (CS.getKind() == ConversionSpecifier::cArg)
393 switch (LM.getKind()) {
394 case LengthModifier::None:
396 case LengthModifier::AsLong:
397 case LengthModifier::AsWide:
398 return ArgType(ArgType::WIntTy, "wint_t");
399 case LengthModifier::AsShort:
400 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
403 return ArgType::Invalid();
407 switch (LM.getKind()) {
408 case LengthModifier::AsLongDouble:
410 return Ctx.LongLongTy;
411 case LengthModifier::None:
413 case LengthModifier::AsInt32:
414 return ArgType(Ctx.IntTy, "__int32");
415 case LengthModifier::AsChar: return ArgType::AnyCharTy;
416 case LengthModifier::AsShort: return Ctx.ShortTy;
417 case LengthModifier::AsLong: return Ctx.LongTy;
418 case LengthModifier::AsLongLong:
419 case LengthModifier::AsQuad:
420 return Ctx.LongLongTy;
421 case LengthModifier::AsInt64:
422 return ArgType(Ctx.LongLongTy, "__int64");
423 case LengthModifier::AsIntMax:
424 return ArgType(Ctx.getIntMaxType(), "intmax_t");
425 case LengthModifier::AsSizeT:
426 // FIXME: How to get the corresponding signed version of size_t?
428 case LengthModifier::AsInt3264:
429 return Ctx.getTargetInfo().getTriple().isArch64Bit()
430 ? ArgType(Ctx.LongLongTy, "__int64")
431 : ArgType(Ctx.IntTy, "__int32");
432 case LengthModifier::AsPtrDiff:
433 return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
434 case LengthModifier::AsAllocate:
435 case LengthModifier::AsMAllocate:
436 case LengthModifier::AsWide:
437 return ArgType::Invalid();
441 switch (LM.getKind()) {
442 case LengthModifier::AsLongDouble:
444 return Ctx.UnsignedLongLongTy;
445 case LengthModifier::None:
446 return Ctx.UnsignedIntTy;
447 case LengthModifier::AsInt32:
448 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
449 case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
450 case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
451 case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
452 case LengthModifier::AsLongLong:
453 case LengthModifier::AsQuad:
454 return Ctx.UnsignedLongLongTy;
455 case LengthModifier::AsInt64:
456 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
457 case LengthModifier::AsIntMax:
458 return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
459 case LengthModifier::AsSizeT:
460 return ArgType(Ctx.getSizeType(), "size_t");
461 case LengthModifier::AsInt3264:
462 return Ctx.getTargetInfo().getTriple().isArch64Bit()
463 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
464 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
465 case LengthModifier::AsPtrDiff:
466 // FIXME: How to get the corresponding unsigned
467 // version of ptrdiff_t?
469 case LengthModifier::AsAllocate:
470 case LengthModifier::AsMAllocate:
471 case LengthModifier::AsWide:
472 return ArgType::Invalid();
475 if (CS.isDoubleArg()) {
476 if (LM.getKind() == LengthModifier::AsLongDouble)
477 return Ctx.LongDoubleTy;
481 if (CS.getKind() == ConversionSpecifier::nArg) {
482 switch (LM.getKind()) {
483 case LengthModifier::None:
484 return ArgType::PtrTo(Ctx.IntTy);
485 case LengthModifier::AsChar:
486 return ArgType::PtrTo(Ctx.SignedCharTy);
487 case LengthModifier::AsShort:
488 return ArgType::PtrTo(Ctx.ShortTy);
489 case LengthModifier::AsLong:
490 return ArgType::PtrTo(Ctx.LongTy);
491 case LengthModifier::AsLongLong:
492 case LengthModifier::AsQuad:
493 return ArgType::PtrTo(Ctx.LongLongTy);
494 case LengthModifier::AsIntMax:
495 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
496 case LengthModifier::AsSizeT:
497 return ArgType(); // FIXME: ssize_t
498 case LengthModifier::AsPtrDiff:
499 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
500 case LengthModifier::AsLongDouble:
501 return ArgType(); // FIXME: Is this a known extension?
502 case LengthModifier::AsAllocate:
503 case LengthModifier::AsMAllocate:
504 case LengthModifier::AsInt32:
505 case LengthModifier::AsInt3264:
506 case LengthModifier::AsInt64:
507 case LengthModifier::AsWide:
508 return ArgType::Invalid();
512 switch (CS.getKind()) {
513 case ConversionSpecifier::sArg:
514 if (LM.getKind() == LengthModifier::AsWideChar) {
516 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
518 return ArgType(ArgType::WCStrTy, "wchar_t *");
520 if (LM.getKind() == LengthModifier::AsWide)
521 return ArgType(ArgType::WCStrTy, "wchar_t *");
522 return ArgType::CStrTy;
523 case ConversionSpecifier::SArg:
525 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
527 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
528 LM.getKind() == LengthModifier::AsShort)
529 return ArgType::CStrTy;
530 return ArgType(ArgType::WCStrTy, "wchar_t *");
531 case ConversionSpecifier::CArg:
533 return ArgType(Ctx.UnsignedShortTy, "unichar");
534 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
535 LM.getKind() == LengthModifier::AsShort)
537 return ArgType(Ctx.WideCharTy, "wchar_t");
538 case ConversionSpecifier::pArg:
539 return ArgType::CPointerTy;
540 case ConversionSpecifier::ObjCObjArg:
541 return ArgType::ObjCPointerTy;
546 // FIXME: Handle other cases.
550 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
551 ASTContext &Ctx, bool IsObjCLiteral) {
552 // %n is different from other conversion specifiers; don't try to fix it.
553 if (CS.getKind() == ConversionSpecifier::nArg)
556 // Handle Objective-C objects first. Note that while the '%@' specifier will
557 // not warn for structure pointer or void pointer arguments (because that's
558 // how CoreFoundation objects are implemented), we only show a fixit for '%@'
559 // if we know it's an object (block, id, class, or __attribute__((NSObject))).
560 if (QT->isObjCRetainableType()) {
564 CS.setKind(ConversionSpecifier::ObjCObjArg);
566 // Disable irrelevant flags
567 HasThousandsGrouping = false;
568 HasPlusPrefix = false;
569 HasSpacePrefix = false;
570 HasAlternativeForm = false;
571 HasLeadingZeroes = false;
572 Precision.setHowSpecified(OptionalAmount::NotSpecified);
573 LM.setKind(LengthModifier::None);
578 // Handle strings next (char *, wchar_t *)
579 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
580 CS.setKind(ConversionSpecifier::sArg);
582 // Disable irrelevant flags
583 HasAlternativeForm = 0;
584 HasLeadingZeroes = 0;
586 // Set the long length modifier for wide characters
587 if (QT->getPointeeType()->isWideCharType())
588 LM.setKind(LengthModifier::AsWideChar);
590 LM.setKind(LengthModifier::None);
595 // If it's an enum, get its underlying type.
596 if (const EnumType *ETy = QT->getAs<EnumType>())
597 QT = ETy->getDecl()->getIntegerType();
599 // We can only work with builtin types.
600 const BuiltinType *BT = QT->getAs<BuiltinType>();
604 // Set length modifier
605 switch (BT->getKind()) {
606 case BuiltinType::Bool:
607 case BuiltinType::WChar_U:
608 case BuiltinType::WChar_S:
609 case BuiltinType::Char16:
610 case BuiltinType::Char32:
611 case BuiltinType::UInt128:
612 case BuiltinType::Int128:
613 case BuiltinType::Half:
614 // Various types which are non-trivial to correct.
617 #define SIGNED_TYPE(Id, SingletonId)
618 #define UNSIGNED_TYPE(Id, SingletonId)
619 #define FLOATING_TYPE(Id, SingletonId)
620 #define BUILTIN_TYPE(Id, SingletonId) \
621 case BuiltinType::Id:
622 #include "clang/AST/BuiltinTypes.def"
623 // Misc other stuff which doesn't make sense here.
626 case BuiltinType::UInt:
627 case BuiltinType::Int:
628 case BuiltinType::Float:
629 case BuiltinType::Double:
630 LM.setKind(LengthModifier::None);
633 case BuiltinType::Char_U:
634 case BuiltinType::UChar:
635 case BuiltinType::Char_S:
636 case BuiltinType::SChar:
637 LM.setKind(LengthModifier::AsChar);
640 case BuiltinType::Short:
641 case BuiltinType::UShort:
642 LM.setKind(LengthModifier::AsShort);
645 case BuiltinType::Long:
646 case BuiltinType::ULong:
647 LM.setKind(LengthModifier::AsLong);
650 case BuiltinType::LongLong:
651 case BuiltinType::ULongLong:
652 LM.setKind(LengthModifier::AsLongLong);
655 case BuiltinType::LongDouble:
656 LM.setKind(LengthModifier::AsLongDouble);
660 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
661 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
662 namedTypeToLengthModifier(QT, LM);
664 // If fixing the length modifier was enough, we might be done.
665 if (hasValidLengthModifier(Ctx.getTargetInfo())) {
666 // If we're going to offer a fix anyway, make sure the sign matches.
667 switch (CS.getKind()) {
668 case ConversionSpecifier::uArg:
669 case ConversionSpecifier::UArg:
670 if (QT->isSignedIntegerType())
671 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
673 case ConversionSpecifier::dArg:
674 case ConversionSpecifier::DArg:
675 case ConversionSpecifier::iArg:
676 if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
677 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
680 // Other specifiers do not have signed/unsigned variants.
684 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
685 if (ATR.isValid() && ATR.matchesType(Ctx, QT))
689 // Set conversion specifier and disable any flags which do not apply to it.
690 // Let typedefs to char fall through to int, as %c is silly for uint8_t.
691 if (!isa<TypedefType>(QT) && QT->isCharType()) {
692 CS.setKind(ConversionSpecifier::cArg);
693 LM.setKind(LengthModifier::None);
694 Precision.setHowSpecified(OptionalAmount::NotSpecified);
695 HasAlternativeForm = 0;
696 HasLeadingZeroes = 0;
699 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
700 else if (QT->isRealFloatingType()) {
701 CS.setKind(ConversionSpecifier::fArg);
703 else if (QT->isSignedIntegerType()) {
704 CS.setKind(ConversionSpecifier::dArg);
705 HasAlternativeForm = 0;
707 else if (QT->isUnsignedIntegerType()) {
708 CS.setKind(ConversionSpecifier::uArg);
709 HasAlternativeForm = 0;
712 llvm_unreachable("Unexpected type");
718 void PrintfSpecifier::toString(raw_ostream &os) const {
719 // Whilst some features have no defined order, we are using the order
720 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
724 if (usesPositionalArg()) {
725 os << getPositionalArgIndex() << "$";
729 if (IsLeftJustified) os << "-";
730 if (HasPlusPrefix) os << "+";
731 if (HasSpacePrefix) os << " ";
732 if (HasAlternativeForm) os << "#";
733 if (HasLeadingZeroes) os << "0";
735 // Minimum field width
736 FieldWidth.toString(os);
738 Precision.toString(os);
741 // Conversion specifier
745 bool PrintfSpecifier::hasValidPlusPrefix() const {
749 // The plus prefix only makes sense for signed conversions
750 switch (CS.getKind()) {
751 case ConversionSpecifier::dArg:
752 case ConversionSpecifier::DArg:
753 case ConversionSpecifier::iArg:
754 case ConversionSpecifier::fArg:
755 case ConversionSpecifier::FArg:
756 case ConversionSpecifier::eArg:
757 case ConversionSpecifier::EArg:
758 case ConversionSpecifier::gArg:
759 case ConversionSpecifier::GArg:
760 case ConversionSpecifier::aArg:
761 case ConversionSpecifier::AArg:
762 case ConversionSpecifier::FreeBSDrArg:
763 case ConversionSpecifier::FreeBSDyArg:
771 bool PrintfSpecifier::hasValidAlternativeForm() const {
772 if (!HasAlternativeForm)
775 // Alternate form flag only valid with the oxXaAeEfFgG conversions
776 switch (CS.getKind()) {
777 case ConversionSpecifier::oArg:
778 case ConversionSpecifier::OArg:
779 case ConversionSpecifier::xArg:
780 case ConversionSpecifier::XArg:
781 case ConversionSpecifier::aArg:
782 case ConversionSpecifier::AArg:
783 case ConversionSpecifier::eArg:
784 case ConversionSpecifier::EArg:
785 case ConversionSpecifier::fArg:
786 case ConversionSpecifier::FArg:
787 case ConversionSpecifier::gArg:
788 case ConversionSpecifier::GArg:
789 case ConversionSpecifier::FreeBSDrArg:
790 case ConversionSpecifier::FreeBSDyArg:
798 bool PrintfSpecifier::hasValidLeadingZeros() const {
799 if (!HasLeadingZeroes)
802 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
803 switch (CS.getKind()) {
804 case ConversionSpecifier::dArg:
805 case ConversionSpecifier::DArg:
806 case ConversionSpecifier::iArg:
807 case ConversionSpecifier::oArg:
808 case ConversionSpecifier::OArg:
809 case ConversionSpecifier::uArg:
810 case ConversionSpecifier::UArg:
811 case ConversionSpecifier::xArg:
812 case ConversionSpecifier::XArg:
813 case ConversionSpecifier::aArg:
814 case ConversionSpecifier::AArg:
815 case ConversionSpecifier::eArg:
816 case ConversionSpecifier::EArg:
817 case ConversionSpecifier::fArg:
818 case ConversionSpecifier::FArg:
819 case ConversionSpecifier::gArg:
820 case ConversionSpecifier::GArg:
821 case ConversionSpecifier::FreeBSDrArg:
822 case ConversionSpecifier::FreeBSDyArg:
830 bool PrintfSpecifier::hasValidSpacePrefix() const {
834 // The space prefix only makes sense for signed conversions
835 switch (CS.getKind()) {
836 case ConversionSpecifier::dArg:
837 case ConversionSpecifier::DArg:
838 case ConversionSpecifier::iArg:
839 case ConversionSpecifier::fArg:
840 case ConversionSpecifier::FArg:
841 case ConversionSpecifier::eArg:
842 case ConversionSpecifier::EArg:
843 case ConversionSpecifier::gArg:
844 case ConversionSpecifier::GArg:
845 case ConversionSpecifier::aArg:
846 case ConversionSpecifier::AArg:
847 case ConversionSpecifier::FreeBSDrArg:
848 case ConversionSpecifier::FreeBSDyArg:
856 bool PrintfSpecifier::hasValidLeftJustified() const {
857 if (!IsLeftJustified)
860 // The left justified flag is valid for all conversions except n
861 switch (CS.getKind()) {
862 case ConversionSpecifier::nArg:
870 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
871 if (!HasThousandsGrouping)
874 switch (CS.getKind()) {
875 case ConversionSpecifier::dArg:
876 case ConversionSpecifier::DArg:
877 case ConversionSpecifier::iArg:
878 case ConversionSpecifier::uArg:
879 case ConversionSpecifier::UArg:
880 case ConversionSpecifier::fArg:
881 case ConversionSpecifier::FArg:
882 case ConversionSpecifier::gArg:
883 case ConversionSpecifier::GArg:
890 bool PrintfSpecifier::hasValidPrecision() const {
891 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
894 // Precision is only valid with the diouxXaAeEfFgGs conversions
895 switch (CS.getKind()) {
896 case ConversionSpecifier::dArg:
897 case ConversionSpecifier::DArg:
898 case ConversionSpecifier::iArg:
899 case ConversionSpecifier::oArg:
900 case ConversionSpecifier::OArg:
901 case ConversionSpecifier::uArg:
902 case ConversionSpecifier::UArg:
903 case ConversionSpecifier::xArg:
904 case ConversionSpecifier::XArg:
905 case ConversionSpecifier::aArg:
906 case ConversionSpecifier::AArg:
907 case ConversionSpecifier::eArg:
908 case ConversionSpecifier::EArg:
909 case ConversionSpecifier::fArg:
910 case ConversionSpecifier::FArg:
911 case ConversionSpecifier::gArg:
912 case ConversionSpecifier::GArg:
913 case ConversionSpecifier::sArg:
914 case ConversionSpecifier::FreeBSDrArg:
915 case ConversionSpecifier::FreeBSDyArg:
922 bool PrintfSpecifier::hasValidFieldWidth() const {
923 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
926 // The field width is valid for all conversions except n
927 switch (CS.getKind()) {
928 case ConversionSpecifier::nArg: