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 "clang/Analysis/Analyses/OSLog.h"
17 #include "FormatStringParsing.h"
18 #include "clang/Basic/TargetInfo.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 = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})";
131 llvm::Regex R(Match);
132 SmallVector<StringRef, 2> Matches;
134 if (R.match(Str, &Matches)) {
135 MatchedStr = Matches[1];
136 I += Matches[0].size();
138 // Set the privacy flag if the privacy annotation in the
139 // comma-delimited segment is at least as strict as the privacy
140 // annotations in previous comma-delimited segments.
141 if (MatchedStr.equals("private"))
142 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;
143 else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
144 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;
146 size_t CommaOrBracePos =
147 Str.find_if([](char c) { return c == ',' || c == '}'; });
149 if (CommaOrBracePos == StringRef::npos) {
150 // Neither a comma nor the closing brace was found.
152 H.HandleIncompleteSpecifier(Start, E - Start);
156 I += CommaOrBracePos + 1;
158 // Continue until the closing brace is found.
159 } while (*(I - 1) == ',');
161 // Set the privacy flag.
162 switch (PrivacyFlags) {
165 case clang::analyze_os_log::OSLogBufferItem::IsPrivate:
166 FS.setIsPrivate(MatchedStr.data());
168 case clang::analyze_os_log::OSLogBufferItem::IsPublic:
169 FS.setIsPublic(MatchedStr.data());
172 llvm_unreachable("Unexpected privacy flag value");
176 // Look for flags (if any).
178 for ( ; I != E; ++I) {
180 default: hasMore = false; break;
182 // FIXME: POSIX specific. Always accept?
183 FS.setHasThousandsGrouping(I);
185 case '-': FS.setIsLeftJustified(I); break;
186 case '+': FS.setHasPlusPrefix(I); break;
187 case ' ': FS.setHasSpacePrefix(I); break;
188 case '#': FS.setHasAlternativeForm(I); break;
189 case '0': FS.setHasLeadingZeros(I); break;
196 // No more characters left?
198 H.HandleIncompleteSpecifier(Start, E - Start);
202 // Look for the field width (if any).
203 if (ParseFieldWidth(H, FS, Start, I, E,
204 FS.usesPositionalArg() ? nullptr : &argIndex))
208 // No more characters left?
210 H.HandleIncompleteSpecifier(Start, E - Start);
214 // Look for the precision (if any).
219 H.HandleIncompleteSpecifier(Start, E - Start);
223 if (ParsePrecision(H, FS, Start, I, E,
224 FS.usesPositionalArg() ? nullptr : &argIndex))
228 // No more characters left?
230 H.HandleIncompleteSpecifier(Start, E - Start);
235 // Look for the length modifier.
236 if (ParseLengthModifier(FS, I, E, LO) && I == E) {
237 // No more characters left?
239 H.HandleIncompleteSpecifier(Start, E - Start);
243 // Look for the Objective-C modifier flags, if any.
244 // We parse these here, even if they don't apply to
245 // the conversion specifier, and then emit an error
246 // later if the conversion specifier isn't '@'. This
247 // enables better recovery, and we don't know if
248 // these flags are applicable until later.
249 const char *ObjCModifierFlagsStart = nullptr,
250 *ObjCModifierFlagsEnd = nullptr;
252 ObjCModifierFlagsStart = I;
256 ObjCModifierFlagsEnd = I;
259 H.HandleIncompleteSpecifier(Start, E - Start);
262 // Did we find the closing ']'?
264 if (ParseObjCFlags(H, FS, flagStart, I, Warn))
269 // There are no separators defined yet for multiple
270 // Objective-C modifier flags. When those are
271 // defined, this is the place to check.
276 // Detect spurious null characters, which are likely errors.
281 // Finally, look for the conversion specifier.
282 const char *conversionPosition = I++;
283 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
284 switch (*conversionPosition) {
287 // C99: 7.19.6.1 (section 8).
288 case '%': k = ConversionSpecifier::PercentArg; break;
289 case 'A': k = ConversionSpecifier::AArg; break;
290 case 'E': k = ConversionSpecifier::EArg; break;
291 case 'F': k = ConversionSpecifier::FArg; break;
292 case 'G': k = ConversionSpecifier::GArg; break;
293 case 'X': k = ConversionSpecifier::XArg; break;
294 case 'a': k = ConversionSpecifier::aArg; break;
295 case 'c': k = ConversionSpecifier::cArg; break;
296 case 'd': k = ConversionSpecifier::dArg; break;
297 case 'e': k = ConversionSpecifier::eArg; break;
298 case 'f': k = ConversionSpecifier::fArg; break;
299 case 'g': k = ConversionSpecifier::gArg; break;
300 case 'i': k = ConversionSpecifier::iArg; break;
301 case 'n': k = ConversionSpecifier::nArg; break;
302 case 'o': k = ConversionSpecifier::oArg; break;
303 case 'p': k = ConversionSpecifier::pArg; break;
304 case 's': k = ConversionSpecifier::sArg; break;
305 case 'u': k = ConversionSpecifier::uArg; break;
306 case 'x': k = ConversionSpecifier::xArg; break;
308 case 'C': k = ConversionSpecifier::CArg; break;
309 case 'S': k = ConversionSpecifier::SArg; break;
310 // Apple extension for os_log
312 k = ConversionSpecifier::PArg;
315 case '@': k = ConversionSpecifier::ObjCObjArg; break;
317 case 'm': k = ConversionSpecifier::PrintErrno; break;
318 // FreeBSD kernel specific.
320 if (isFreeBSDKPrintf)
321 k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
324 if (isFreeBSDKPrintf)
325 k = ConversionSpecifier::FreeBSDrArg; // int
328 if (isFreeBSDKPrintf)
329 k = ConversionSpecifier::FreeBSDyArg; // int
333 if (isFreeBSDKPrintf)
334 k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
335 else if (Target.getTriple().isOSDarwin())
336 k = ConversionSpecifier::DArg;
339 if (Target.getTriple().isOSDarwin())
340 k = ConversionSpecifier::OArg;
343 if (Target.getTriple().isOSDarwin())
344 k = ConversionSpecifier::UArg;
348 if (Target.getTriple().isOSMSVCRT())
349 k = ConversionSpecifier::ZArg;
352 // Check to see if we used the Objective-C modifier flags with
353 // a conversion specifier other than '@'.
354 if (k != ConversionSpecifier::ObjCObjArg &&
355 k != ConversionSpecifier::InvalidSpecifier &&
356 ObjCModifierFlagsStart) {
357 H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
358 ObjCModifierFlagsEnd + 1,
363 PrintfConversionSpecifier CS(conversionPosition, k);
364 FS.setConversionSpecifier(CS);
365 if (CS.consumesDataArgument() && !FS.usesPositionalArg())
366 FS.setArgIndex(argIndex++);
367 // FreeBSD kernel specific.
368 if (k == ConversionSpecifier::FreeBSDbArg ||
369 k == ConversionSpecifier::FreeBSDDArg)
372 if (k == ConversionSpecifier::InvalidSpecifier) {
373 unsigned Len = I - Start;
374 if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
375 CS.setEndScanList(Start + Len);
376 FS.setConversionSpecifier(CS);
378 // Assume the conversion takes one argument.
379 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
381 return PrintfSpecifierResult(Start, FS);
384 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
387 const LangOptions &LO,
388 const TargetInfo &Target,
389 bool isFreeBSDKPrintf) {
391 unsigned argIndex = 0;
393 // Keep looking for a format specifier until we have exhausted the string.
395 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
398 // Did a fail-stop error of any kind occur when parsing the specifier?
399 // If so, don't do any more processing.
400 if (FSR.shouldStop())
402 // Did we exhaust the string or encounter an error that
403 // we can recover from?
406 // We have a format specifier. Pass it to the callback.
407 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
411 assert(I == E && "Format string not exhausted");
415 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
417 const LangOptions &LO,
418 const TargetInfo &Target) {
420 unsigned argIndex = 0;
422 // Keep looking for a %s format specifier until we have exhausted the string.
423 FormatStringHandler H;
425 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
428 // Did a fail-stop error of any kind occur when parsing the specifier?
429 // If so, don't do any more processing.
430 if (FSR.shouldStop())
432 // Did we exhaust the string or encounter an error that
433 // we can recover from?
436 const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
437 // Return true if this a %s format specifier.
438 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
444 //===----------------------------------------------------------------------===//
445 // Methods on PrintfSpecifier.
446 //===----------------------------------------------------------------------===//
448 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
449 bool IsObjCLiteral) const {
450 const PrintfConversionSpecifier &CS = getConversionSpecifier();
452 if (!CS.consumesDataArgument())
453 return ArgType::Invalid();
455 if (CS.getKind() == ConversionSpecifier::cArg)
456 switch (LM.getKind()) {
457 case LengthModifier::None:
459 case LengthModifier::AsLong:
460 case LengthModifier::AsWide:
461 return ArgType(ArgType::WIntTy, "wint_t");
462 case LengthModifier::AsShort:
463 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
467 return ArgType::Invalid();
471 switch (LM.getKind()) {
472 case LengthModifier::AsLongDouble:
474 return Ctx.LongLongTy;
475 case LengthModifier::None:
477 case LengthModifier::AsInt32:
478 return ArgType(Ctx.IntTy, "__int32");
479 case LengthModifier::AsChar: return ArgType::AnyCharTy;
480 case LengthModifier::AsShort: return Ctx.ShortTy;
481 case LengthModifier::AsLong: return Ctx.LongTy;
482 case LengthModifier::AsLongLong:
483 case LengthModifier::AsQuad:
484 return Ctx.LongLongTy;
485 case LengthModifier::AsInt64:
486 return ArgType(Ctx.LongLongTy, "__int64");
487 case LengthModifier::AsIntMax:
488 return ArgType(Ctx.getIntMaxType(), "intmax_t");
489 case LengthModifier::AsSizeT:
490 return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
491 case LengthModifier::AsInt3264:
492 return Ctx.getTargetInfo().getTriple().isArch64Bit()
493 ? ArgType(Ctx.LongLongTy, "__int64")
494 : ArgType(Ctx.IntTy, "__int32");
495 case LengthModifier::AsPtrDiff:
496 return ArgType::makePtrdiffT(
497 ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
498 case LengthModifier::AsAllocate:
499 case LengthModifier::AsMAllocate:
500 case LengthModifier::AsWide:
501 return ArgType::Invalid();
505 switch (LM.getKind()) {
506 case LengthModifier::AsLongDouble:
508 return Ctx.UnsignedLongLongTy;
509 case LengthModifier::None:
510 return Ctx.UnsignedIntTy;
511 case LengthModifier::AsInt32:
512 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
513 case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
514 case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
515 case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
516 case LengthModifier::AsLongLong:
517 case LengthModifier::AsQuad:
518 return Ctx.UnsignedLongLongTy;
519 case LengthModifier::AsInt64:
520 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
521 case LengthModifier::AsIntMax:
522 return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
523 case LengthModifier::AsSizeT:
524 return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
525 case LengthModifier::AsInt3264:
526 return Ctx.getTargetInfo().getTriple().isArch64Bit()
527 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
528 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
529 case LengthModifier::AsPtrDiff:
530 return ArgType::makePtrdiffT(
531 ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
532 case LengthModifier::AsAllocate:
533 case LengthModifier::AsMAllocate:
534 case LengthModifier::AsWide:
535 return ArgType::Invalid();
538 if (CS.isDoubleArg()) {
539 if (LM.getKind() == LengthModifier::AsLongDouble)
540 return Ctx.LongDoubleTy;
544 if (CS.getKind() == ConversionSpecifier::nArg) {
545 switch (LM.getKind()) {
546 case LengthModifier::None:
547 return ArgType::PtrTo(Ctx.IntTy);
548 case LengthModifier::AsChar:
549 return ArgType::PtrTo(Ctx.SignedCharTy);
550 case LengthModifier::AsShort:
551 return ArgType::PtrTo(Ctx.ShortTy);
552 case LengthModifier::AsLong:
553 return ArgType::PtrTo(Ctx.LongTy);
554 case LengthModifier::AsLongLong:
555 case LengthModifier::AsQuad:
556 return ArgType::PtrTo(Ctx.LongLongTy);
557 case LengthModifier::AsIntMax:
558 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
559 case LengthModifier::AsSizeT:
560 return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
561 case LengthModifier::AsPtrDiff:
562 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
563 case LengthModifier::AsLongDouble:
564 return ArgType(); // FIXME: Is this a known extension?
565 case LengthModifier::AsAllocate:
566 case LengthModifier::AsMAllocate:
567 case LengthModifier::AsInt32:
568 case LengthModifier::AsInt3264:
569 case LengthModifier::AsInt64:
570 case LengthModifier::AsWide:
571 return ArgType::Invalid();
575 switch (CS.getKind()) {
576 case ConversionSpecifier::sArg:
577 if (LM.getKind() == LengthModifier::AsWideChar) {
579 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
581 return ArgType(ArgType::WCStrTy, "wchar_t *");
583 if (LM.getKind() == LengthModifier::AsWide)
584 return ArgType(ArgType::WCStrTy, "wchar_t *");
585 return ArgType::CStrTy;
586 case ConversionSpecifier::SArg:
588 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
590 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
591 LM.getKind() == LengthModifier::AsShort)
592 return ArgType::CStrTy;
593 return ArgType(ArgType::WCStrTy, "wchar_t *");
594 case ConversionSpecifier::CArg:
596 return ArgType(Ctx.UnsignedShortTy, "unichar");
597 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
598 LM.getKind() == LengthModifier::AsShort)
600 return ArgType(Ctx.WideCharTy, "wchar_t");
601 case ConversionSpecifier::pArg:
602 case ConversionSpecifier::PArg:
603 return ArgType::CPointerTy;
604 case ConversionSpecifier::ObjCObjArg:
605 return ArgType::ObjCPointerTy;
610 // FIXME: Handle other cases.
614 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
615 ASTContext &Ctx, bool IsObjCLiteral) {
616 // %n is different from other conversion specifiers; don't try to fix it.
617 if (CS.getKind() == ConversionSpecifier::nArg)
620 // Handle Objective-C objects first. Note that while the '%@' specifier will
621 // not warn for structure pointer or void pointer arguments (because that's
622 // how CoreFoundation objects are implemented), we only show a fixit for '%@'
623 // if we know it's an object (block, id, class, or __attribute__((NSObject))).
624 if (QT->isObjCRetainableType()) {
628 CS.setKind(ConversionSpecifier::ObjCObjArg);
630 // Disable irrelevant flags
631 HasThousandsGrouping = false;
632 HasPlusPrefix = false;
633 HasSpacePrefix = false;
634 HasAlternativeForm = false;
635 HasLeadingZeroes = false;
636 Precision.setHowSpecified(OptionalAmount::NotSpecified);
637 LM.setKind(LengthModifier::None);
642 // Handle strings next (char *, wchar_t *)
643 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
644 CS.setKind(ConversionSpecifier::sArg);
646 // Disable irrelevant flags
647 HasAlternativeForm = 0;
648 HasLeadingZeroes = 0;
650 // Set the long length modifier for wide characters
651 if (QT->getPointeeType()->isWideCharType())
652 LM.setKind(LengthModifier::AsWideChar);
654 LM.setKind(LengthModifier::None);
659 // If it's an enum, get its underlying type.
660 if (const EnumType *ETy = QT->getAs<EnumType>())
661 QT = ETy->getDecl()->getIntegerType();
663 // We can only work with builtin types.
664 const BuiltinType *BT = QT->getAs<BuiltinType>();
668 // Set length modifier
669 switch (BT->getKind()) {
670 case BuiltinType::Bool:
671 case BuiltinType::WChar_U:
672 case BuiltinType::WChar_S:
673 case BuiltinType::Char8: // FIXME: Treat like 'char'?
674 case BuiltinType::Char16:
675 case BuiltinType::Char32:
676 case BuiltinType::UInt128:
677 case BuiltinType::Int128:
678 case BuiltinType::Half:
679 case BuiltinType::Float16:
680 case BuiltinType::Float128:
681 case BuiltinType::ShortAccum:
682 case BuiltinType::Accum:
683 case BuiltinType::LongAccum:
684 case BuiltinType::UShortAccum:
685 case BuiltinType::UAccum:
686 case BuiltinType::ULongAccum:
687 case BuiltinType::ShortFract:
688 case BuiltinType::Fract:
689 case BuiltinType::LongFract:
690 case BuiltinType::UShortFract:
691 case BuiltinType::UFract:
692 case BuiltinType::ULongFract:
693 case BuiltinType::SatShortAccum:
694 case BuiltinType::SatAccum:
695 case BuiltinType::SatLongAccum:
696 case BuiltinType::SatUShortAccum:
697 case BuiltinType::SatUAccum:
698 case BuiltinType::SatULongAccum:
699 case BuiltinType::SatShortFract:
700 case BuiltinType::SatFract:
701 case BuiltinType::SatLongFract:
702 case BuiltinType::SatUShortFract:
703 case BuiltinType::SatUFract:
704 case BuiltinType::SatULongFract:
705 // Various types which are non-trivial to correct.
708 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
709 case BuiltinType::Id:
710 #include "clang/Basic/OpenCLImageTypes.def"
711 #define SIGNED_TYPE(Id, SingletonId)
712 #define UNSIGNED_TYPE(Id, SingletonId)
713 #define FLOATING_TYPE(Id, SingletonId)
714 #define BUILTIN_TYPE(Id, SingletonId) \
715 case BuiltinType::Id:
716 #include "clang/AST/BuiltinTypes.def"
717 // Misc other stuff which doesn't make sense here.
720 case BuiltinType::UInt:
721 case BuiltinType::Int:
722 case BuiltinType::Float:
723 case BuiltinType::Double:
724 LM.setKind(LengthModifier::None);
727 case BuiltinType::Char_U:
728 case BuiltinType::UChar:
729 case BuiltinType::Char_S:
730 case BuiltinType::SChar:
731 LM.setKind(LengthModifier::AsChar);
734 case BuiltinType::Short:
735 case BuiltinType::UShort:
736 LM.setKind(LengthModifier::AsShort);
739 case BuiltinType::Long:
740 case BuiltinType::ULong:
741 LM.setKind(LengthModifier::AsLong);
744 case BuiltinType::LongLong:
745 case BuiltinType::ULongLong:
746 LM.setKind(LengthModifier::AsLongLong);
749 case BuiltinType::LongDouble:
750 LM.setKind(LengthModifier::AsLongDouble);
754 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
755 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
756 namedTypeToLengthModifier(QT, LM);
758 // If fixing the length modifier was enough, we might be done.
759 if (hasValidLengthModifier(Ctx.getTargetInfo())) {
760 // If we're going to offer a fix anyway, make sure the sign matches.
761 switch (CS.getKind()) {
762 case ConversionSpecifier::uArg:
763 case ConversionSpecifier::UArg:
764 if (QT->isSignedIntegerType())
765 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
767 case ConversionSpecifier::dArg:
768 case ConversionSpecifier::DArg:
769 case ConversionSpecifier::iArg:
770 if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
771 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
774 // Other specifiers do not have signed/unsigned variants.
778 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
779 if (ATR.isValid() && ATR.matchesType(Ctx, QT))
783 // Set conversion specifier and disable any flags which do not apply to it.
784 // Let typedefs to char fall through to int, as %c is silly for uint8_t.
785 if (!isa<TypedefType>(QT) && QT->isCharType()) {
786 CS.setKind(ConversionSpecifier::cArg);
787 LM.setKind(LengthModifier::None);
788 Precision.setHowSpecified(OptionalAmount::NotSpecified);
789 HasAlternativeForm = 0;
790 HasLeadingZeroes = 0;
793 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
794 else if (QT->isRealFloatingType()) {
795 CS.setKind(ConversionSpecifier::fArg);
797 else if (QT->isSignedIntegerType()) {
798 CS.setKind(ConversionSpecifier::dArg);
799 HasAlternativeForm = 0;
801 else if (QT->isUnsignedIntegerType()) {
802 CS.setKind(ConversionSpecifier::uArg);
803 HasAlternativeForm = 0;
806 llvm_unreachable("Unexpected type");
812 void PrintfSpecifier::toString(raw_ostream &os) const {
813 // Whilst some features have no defined order, we are using the order
814 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
818 if (usesPositionalArg()) {
819 os << getPositionalArgIndex() << "$";
823 if (IsLeftJustified) os << "-";
824 if (HasPlusPrefix) os << "+";
825 if (HasSpacePrefix) os << " ";
826 if (HasAlternativeForm) os << "#";
827 if (HasLeadingZeroes) os << "0";
829 // Minimum field width
830 FieldWidth.toString(os);
832 Precision.toString(os);
835 // Conversion specifier
839 bool PrintfSpecifier::hasValidPlusPrefix() const {
843 // The plus prefix only makes sense for signed conversions
844 switch (CS.getKind()) {
845 case ConversionSpecifier::dArg:
846 case ConversionSpecifier::DArg:
847 case ConversionSpecifier::iArg:
848 case ConversionSpecifier::fArg:
849 case ConversionSpecifier::FArg:
850 case ConversionSpecifier::eArg:
851 case ConversionSpecifier::EArg:
852 case ConversionSpecifier::gArg:
853 case ConversionSpecifier::GArg:
854 case ConversionSpecifier::aArg:
855 case ConversionSpecifier::AArg:
856 case ConversionSpecifier::FreeBSDrArg:
857 case ConversionSpecifier::FreeBSDyArg:
865 bool PrintfSpecifier::hasValidAlternativeForm() const {
866 if (!HasAlternativeForm)
869 // Alternate form flag only valid with the oxXaAeEfFgG conversions
870 switch (CS.getKind()) {
871 case ConversionSpecifier::oArg:
872 case ConversionSpecifier::OArg:
873 case ConversionSpecifier::xArg:
874 case ConversionSpecifier::XArg:
875 case ConversionSpecifier::aArg:
876 case ConversionSpecifier::AArg:
877 case ConversionSpecifier::eArg:
878 case ConversionSpecifier::EArg:
879 case ConversionSpecifier::fArg:
880 case ConversionSpecifier::FArg:
881 case ConversionSpecifier::gArg:
882 case ConversionSpecifier::GArg:
883 case ConversionSpecifier::FreeBSDrArg:
884 case ConversionSpecifier::FreeBSDyArg:
892 bool PrintfSpecifier::hasValidLeadingZeros() const {
893 if (!HasLeadingZeroes)
896 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
897 switch (CS.getKind()) {
898 case ConversionSpecifier::dArg:
899 case ConversionSpecifier::DArg:
900 case ConversionSpecifier::iArg:
901 case ConversionSpecifier::oArg:
902 case ConversionSpecifier::OArg:
903 case ConversionSpecifier::uArg:
904 case ConversionSpecifier::UArg:
905 case ConversionSpecifier::xArg:
906 case ConversionSpecifier::XArg:
907 case ConversionSpecifier::aArg:
908 case ConversionSpecifier::AArg:
909 case ConversionSpecifier::eArg:
910 case ConversionSpecifier::EArg:
911 case ConversionSpecifier::fArg:
912 case ConversionSpecifier::FArg:
913 case ConversionSpecifier::gArg:
914 case ConversionSpecifier::GArg:
915 case ConversionSpecifier::FreeBSDrArg:
916 case ConversionSpecifier::FreeBSDyArg:
924 bool PrintfSpecifier::hasValidSpacePrefix() const {
928 // The space prefix only makes sense for signed conversions
929 switch (CS.getKind()) {
930 case ConversionSpecifier::dArg:
931 case ConversionSpecifier::DArg:
932 case ConversionSpecifier::iArg:
933 case ConversionSpecifier::fArg:
934 case ConversionSpecifier::FArg:
935 case ConversionSpecifier::eArg:
936 case ConversionSpecifier::EArg:
937 case ConversionSpecifier::gArg:
938 case ConversionSpecifier::GArg:
939 case ConversionSpecifier::aArg:
940 case ConversionSpecifier::AArg:
941 case ConversionSpecifier::FreeBSDrArg:
942 case ConversionSpecifier::FreeBSDyArg:
950 bool PrintfSpecifier::hasValidLeftJustified() const {
951 if (!IsLeftJustified)
954 // The left justified flag is valid for all conversions except n
955 switch (CS.getKind()) {
956 case ConversionSpecifier::nArg:
964 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
965 if (!HasThousandsGrouping)
968 switch (CS.getKind()) {
969 case ConversionSpecifier::dArg:
970 case ConversionSpecifier::DArg:
971 case ConversionSpecifier::iArg:
972 case ConversionSpecifier::uArg:
973 case ConversionSpecifier::UArg:
974 case ConversionSpecifier::fArg:
975 case ConversionSpecifier::FArg:
976 case ConversionSpecifier::gArg:
977 case ConversionSpecifier::GArg:
984 bool PrintfSpecifier::hasValidPrecision() const {
985 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
988 // Precision is only valid with the diouxXaAeEfFgGsP conversions
989 switch (CS.getKind()) {
990 case ConversionSpecifier::dArg:
991 case ConversionSpecifier::DArg:
992 case ConversionSpecifier::iArg:
993 case ConversionSpecifier::oArg:
994 case ConversionSpecifier::OArg:
995 case ConversionSpecifier::uArg:
996 case ConversionSpecifier::UArg:
997 case ConversionSpecifier::xArg:
998 case ConversionSpecifier::XArg:
999 case ConversionSpecifier::aArg:
1000 case ConversionSpecifier::AArg:
1001 case ConversionSpecifier::eArg:
1002 case ConversionSpecifier::EArg:
1003 case ConversionSpecifier::fArg:
1004 case ConversionSpecifier::FArg:
1005 case ConversionSpecifier::gArg:
1006 case ConversionSpecifier::GArg:
1007 case ConversionSpecifier::sArg:
1008 case ConversionSpecifier::FreeBSDrArg:
1009 case ConversionSpecifier::FreeBSDyArg:
1010 case ConversionSpecifier::PArg:
1017 bool PrintfSpecifier::hasValidFieldWidth() const {
1018 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1021 // The field width is valid for all conversions except n
1022 switch (CS.getKind()) {
1023 case ConversionSpecifier::nArg: