clang 22.0.0git
PrintfFormatString.cpp
Go to the documentation of this file.
1//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Handling of format string in printf and friends. The structure of format
10// strings for fprintf() are described in C99 7.19.6.1.
11//
12//===----------------------------------------------------------------------===//
13
14#include "FormatStringParsing.h"
16#include "clang/AST/OSLog.h"
18#include "llvm/Support/Regex.h"
19
26
27using namespace clang;
28
31
32//===----------------------------------------------------------------------===//
33// Methods for parsing format strings.
34//===----------------------------------------------------------------------===//
35
37
39 const char *Start, const char *&Beg, const char *E,
40 unsigned *argIndex) {
41 if (argIndex) {
42 FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
43 } else {
44 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
46 if (Amt.isInvalid())
47 return true;
48 FS.setPrecision(Amt);
49 }
50 return false;
51}
52
54 const char *FlagBeg, const char *E, bool Warn) {
55 StringRef Flag(FlagBeg, E - FlagBeg);
56 // Currently there is only one flag.
57 if (Flag == "tt") {
58 FS.setHasObjCTechnicalTerm(FlagBeg);
59 return false;
60 }
61 // Handle either the case of no flag or an invalid flag.
62 if (Warn) {
63 if (Flag == "")
64 H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg);
65 else
66 H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg);
67 }
68 return true;
69}
70
72 const char *&Beg,
73 const char *E,
74 unsigned &argIndex,
75 const LangOptions &LO,
76 const TargetInfo &Target,
77 bool Warn,
78 bool isFreeBSDKPrintf) {
79
80 using namespace clang::analyze_format_string;
81 using namespace clang::analyze_printf;
82
83 const char *I = Beg;
84 const char *Start = nullptr;
85 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
86
87 // Look for a '%' character that indicates the start of a format specifier.
88 for ( ; I != E ; ++I) {
89 char c = *I;
90 if (c == '\0') {
91 // Detect spurious null characters, which are likely errors.
92 H.HandleNullChar(I);
93 return true;
94 }
95 if (c == '%') {
96 Start = I++; // Record the start of the format specifier.
97 break;
98 }
99 }
100
101 // No format specifier found?
102 if (!Start)
103 return false;
104
105 if (I == E) {
106 // No more characters left?
107 if (Warn)
108 H.HandleIncompleteSpecifier(Start, E - Start);
109 return true;
110 }
111
113 if (ParseArgPosition(H, FS, Start, I, E))
114 return true;
115
116 if (I == E) {
117 // No more characters left?
118 if (Warn)
119 H.HandleIncompleteSpecifier(Start, E - Start);
120 return true;
121 }
122
123 if (*I == '{') {
124 ++I;
125 unsigned char PrivacyFlags = 0;
126 StringRef MatchedStr;
127
128 do {
129 StringRef Str(I, E - I);
130 std::string Match = "^[[:space:]]*"
131 "(private|public|sensitive|mask\\.[^[:space:],}]*)"
132 "[[:space:]]*(,|})";
133 llvm::Regex R(Match);
135
136 if (R.match(Str, &Matches)) {
137 MatchedStr = Matches[1];
138 I += Matches[0].size();
139
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.starts_with("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 == "sensitive")
151 else if (PrivacyFlags !=
153 MatchedStr == "private")
155 else if (PrivacyFlags == 0 && MatchedStr == "public")
157 } else {
158 size_t CommaOrBracePos =
159 Str.find_if([](char c) { return c == ',' || c == '}'; });
160
161 if (CommaOrBracePos == StringRef::npos) {
162 // Neither a comma nor the closing brace was found.
163 if (Warn)
164 H.HandleIncompleteSpecifier(Start, E - Start);
165 return true;
166 }
167
168 I += CommaOrBracePos + 1;
169 }
170 // Continue until the closing brace is found.
171 } while (*(I - 1) == ',');
172
173 // Set the privacy flag.
174 switch (PrivacyFlags) {
175 case 0:
176 break;
178 FS.setIsPrivate(MatchedStr.data());
179 break;
181 FS.setIsPublic(MatchedStr.data());
182 break;
184 FS.setIsSensitive(MatchedStr.data());
185 break;
186 default:
187 llvm_unreachable("Unexpected privacy flag value");
188 }
189 }
190
191 // Look for flags (if any).
192 bool hasMore = true;
193 for ( ; I != E; ++I) {
194 switch (*I) {
195 default: hasMore = false; break;
196 case '\'':
197 // FIXME: POSIX specific. Always accept?
198 FS.setHasThousandsGrouping(I);
199 break;
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;
205 }
206 if (!hasMore)
207 break;
208 }
209
210 if (I == E) {
211 // No more characters left?
212 if (Warn)
213 H.HandleIncompleteSpecifier(Start, E - Start);
214 return true;
215 }
216
217 // Look for the field width (if any).
218 if (ParseFieldWidth(H, FS, Start, I, E,
219 FS.usesPositionalArg() ? nullptr : &argIndex))
220 return true;
221
222 if (I == E) {
223 // No more characters left?
224 if (Warn)
225 H.HandleIncompleteSpecifier(Start, E - Start);
226 return true;
227 }
228
229 // Look for the precision (if any).
230 if (*I == '.') {
231 ++I;
232 if (I == E) {
233 if (Warn)
234 H.HandleIncompleteSpecifier(Start, E - Start);
235 return true;
236 }
237
238 if (ParsePrecision(H, FS, Start, I, E,
239 FS.usesPositionalArg() ? nullptr : &argIndex))
240 return true;
241
242 if (I == E) {
243 // No more characters left?
244 if (Warn)
245 H.HandleIncompleteSpecifier(Start, E - Start);
246 return true;
247 }
248 }
249
250 if (ParseVectorModifier(H, FS, I, E, LO))
251 return true;
252
253 // Look for the length modifier.
254 if (ParseLengthModifier(FS, I, E, LO) && I == E) {
255 // No more characters left?
256 if (Warn)
257 H.HandleIncompleteSpecifier(Start, E - Start);
258 return true;
259 }
260
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;
269 if (*I == '[') {
270 ObjCModifierFlagsStart = I;
271 ++I;
272 auto flagStart = I;
273 for (;; ++I) {
274 ObjCModifierFlagsEnd = I;
275 if (I == E) {
276 if (Warn)
277 H.HandleIncompleteSpecifier(Start, E - Start);
278 return true;
279 }
280 // Did we find the closing ']'?
281 if (*I == ']') {
282 if (ParseObjCFlags(H, FS, flagStart, I, Warn))
283 return true;
284 ++I;
285 break;
286 }
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.
290 }
291 }
292
293 if (*I == '\0') {
294 // Detect spurious null characters, which are likely errors.
295 H.HandleNullChar(I);
296 return true;
297 }
298
299 // Finally, look for the conversion specifier.
300 const char *conversionPosition = I++;
302 switch (*conversionPosition) {
303 default:
304 break;
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;
319 case 'n':
320 // Not handled, but reserved in OpenCL.
321 if (!LO.OpenCL)
323 break;
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;
329 // C23.
330 case 'b':
331 if (isFreeBSDKPrintf)
332 k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
333 else
335 break;
336 case 'B': k = ConversionSpecifier::BArg; break;
337 // POSIX specific.
338 case 'C': k = ConversionSpecifier::CArg; break;
339 case 'S': k = ConversionSpecifier::SArg; break;
340 // Apple extension for os_log
341 case 'P':
343 break;
344 // Objective-C.
345 case '@': k = ConversionSpecifier::ObjCObjArg; break;
346 // Glibc specific.
347 case 'm': k = ConversionSpecifier::PrintErrno; break;
348 case 'r':
349 if (isFreeBSDKPrintf)
351 else if (LO.FixedPoint)
353 break;
354 case 'y':
355 if (isFreeBSDKPrintf)
357 break;
358 // Apple-specific.
359 case 'D':
360 if (isFreeBSDKPrintf)
361 k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
362 else if (Target.getTriple().isOSDarwin())
364 break;
365 case 'O':
366 if (Target.getTriple().isOSDarwin())
368 break;
369 case 'U':
370 if (Target.getTriple().isOSDarwin())
372 break;
373 // MS specific.
374 case 'Z':
375 if (Target.getTriple().isOSMSVCRT())
377 break;
378 // ISO/IEC TR 18037 (fixed-point) specific.
379 // NOTE: 'r' is handled up above since FreeBSD also supports %r.
380 case 'k':
381 if (LO.FixedPoint)
383 break;
384 case 'K':
385 if (LO.FixedPoint)
387 break;
388 case 'R':
389 if (LO.FixedPoint)
391 break;
392 }
393
394 // Check to see if we used the Objective-C modifier flags with
395 // a conversion specifier other than '@'.
398 ObjCModifierFlagsStart) {
399 H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
400 ObjCModifierFlagsEnd + 1,
401 conversionPosition);
402 return true;
403 }
404
405 PrintfConversionSpecifier CS(conversionPosition, k);
406 FS.setConversionSpecifier(CS);
407 if (CS.consumesDataArgument() && !FS.usesPositionalArg())
408 FS.setArgIndex(argIndex++);
409 // FreeBSD kernel specific.
412 argIndex++;
413
415 unsigned Len = I - Start;
416 if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
417 CS.setEndScanList(Start + Len);
418 FS.setConversionSpecifier(CS);
419 }
420 // Assume the conversion takes one argument.
421 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
422 }
423 return PrintfSpecifierResult(Start, FS);
424}
425
427 const char *I,
428 const char *E,
429 const LangOptions &LO,
430 const TargetInfo &Target,
431 bool isFreeBSDKPrintf) {
432
433 unsigned argIndex = 0;
434
435 // Keep looking for a format specifier until we have exhausted the string.
436 while (I != E) {
437 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
438 LO, Target, true,
439 isFreeBSDKPrintf);
440 // Did a fail-stop error of any kind occur when parsing the specifier?
441 // If so, don't do any more processing.
442 if (FSR.shouldStop())
443 return true;
444 // Did we exhaust the string or encounter an error that
445 // we can recover from?
446 if (!FSR.hasValue())
447 continue;
448 // We have a format specifier. Pass it to the callback.
449 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
450 I - FSR.getStart(), Target))
451 return true;
452 }
453 assert(I == E && "Format string not exhausted");
454 return false;
455}
456
458 const char *E,
459 const LangOptions &LO,
460 const TargetInfo &Target) {
461
462 unsigned argIndex = 0;
463
464 // Keep looking for a %s format specifier until we have exhausted the string.
466 while (I != E) {
467 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
468 LO, Target, false,
469 false);
470 // Did a fail-stop error of any kind occur when parsing the specifier?
471 // If so, don't do any more processing.
472 if (FSR.shouldStop())
473 return false;
474 // Did we exhaust the string or encounter an error that
475 // we can recover from?
476 if (!FSR.hasValue())
477 continue;
479 // Return true if this a %s format specifier.
480 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
481 return true;
482 }
483 return false;
484}
485
487 const char *Begin, const char *End, const LangOptions &LO,
488 const TargetInfo &Target) {
489 unsigned ArgIndex = 0;
490 // Keep looking for a formatting specifier until we have exhausted the string.
492 while (Begin != End) {
493 const PrintfSpecifierResult &FSR =
494 ParsePrintfSpecifier(H, Begin, End, ArgIndex, LO, Target, false, false);
495 if (FSR.shouldStop())
496 break;
497 if (FSR.hasValue())
498 return true;
499 }
500 return false;
501}
502
503//===----------------------------------------------------------------------===//
504// Methods on PrintfSpecifier.
505//===----------------------------------------------------------------------===//
506
507ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
508 bool IsObjCLiteral) const {
509 if (CS.getKind() == ConversionSpecifier::cArg)
510 switch (LM.getKind()) {
512 return Ctx.IntTy;
515 return ArgType(ArgType::WIntTy, "wint_t");
517 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
518 return Ctx.IntTy;
519 [[fallthrough]];
520 default:
521 return ArgType::Invalid();
522 }
523
524 if (CS.isIntArg())
525 switch (LM.getKind()) {
527 // GNU extension.
528 return Ctx.LongLongTy;
531 return Ctx.IntTy;
533 return ArgType(Ctx.IntTy, "__int32");
535 return ArgType::AnyCharTy;
536 case LengthModifier::AsShort: return Ctx.ShortTy;
537 case LengthModifier::AsLong: return Ctx.LongTy;
540 return Ctx.LongLongTy;
542 return ArgType(Ctx.LongLongTy, "__int64");
544 return ArgType(Ctx.getIntMaxType(), "intmax_t");
546 return ArgType::makeSizeT(
547 ArgType(Ctx.getSignedSizeType(), "signed size_t"));
549 return Ctx.getTargetInfo().getTriple().isArch64Bit()
550 ? ArgType(Ctx.LongLongTy, "__int64")
551 : ArgType(Ctx.IntTy, "__int32");
554 ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
558 return ArgType::Invalid();
559 }
560
561 if (CS.isUIntArg())
562 switch (LM.getKind()) {
564 // GNU extension.
565 return Ctx.UnsignedLongLongTy;
568 return Ctx.UnsignedIntTy;
570 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
571 case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
573 case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
576 return Ctx.UnsignedLongLongTy;
578 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
580 return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
582 return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
584 return Ctx.getTargetInfo().getTriple().isArch64Bit()
585 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
586 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
589 ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
593 return ArgType::Invalid();
594 }
595
596 if (CS.isDoubleArg()) {
597 if (!VectorNumElts.isInvalid()) {
598 switch (LM.getKind()) {
600 return Ctx.HalfTy;
602 return Ctx.FloatTy;
604 default:
605 return Ctx.DoubleTy;
606 }
607 }
608
610 return Ctx.LongDoubleTy;
611 return Ctx.DoubleTy;
612 }
613
614 if (CS.getKind() == ConversionSpecifier::nArg) {
615 switch (LM.getKind()) {
617 return ArgType::PtrTo(Ctx.IntTy);
619 return ArgType::PtrTo(Ctx.SignedCharTy);
621 return ArgType::PtrTo(Ctx.ShortTy);
623 return ArgType::PtrTo(Ctx.LongTy);
626 return ArgType::PtrTo(Ctx.LongLongTy);
628 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
631 ArgType(Ctx.getSignedSizeType(), "signed size_t")));
634 ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")));
636 return ArgType(); // FIXME: Is this a known extension?
643 return ArgType::Invalid();
645 llvm_unreachable("only used for OpenCL which doesn not handle nArg");
646 }
647 }
648
649 if (CS.isFixedPointArg() && !Ctx.getLangOpts().FixedPoint)
650 return ArgType::Invalid();
651
652 switch (CS.getKind()) {
653 case ConversionSpecifier::sArg:
655 if (IsObjCLiteral)
657 "const unichar *");
658 return ArgType(ArgType::WCStrTy, "wchar_t *");
659 }
661 return ArgType(ArgType::WCStrTy, "wchar_t *");
662 return ArgType::CStrTy;
663 case ConversionSpecifier::SArg:
664 if (IsObjCLiteral)
666 "const unichar *");
667 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
669 return ArgType::CStrTy;
670 return ArgType(ArgType::WCStrTy, "wchar_t *");
671 case ConversionSpecifier::CArg:
672 if (IsObjCLiteral)
673 return ArgType(Ctx.UnsignedShortTy, "unichar");
674 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
676 return Ctx.IntTy;
677 return ArgType(Ctx.WideCharTy, "wchar_t");
678 case ConversionSpecifier::pArg:
679 case ConversionSpecifier::PArg:
680 return ArgType::CPointerTy;
681 case ConversionSpecifier::ObjCObjArg:
683 case ConversionSpecifier::kArg:
684 switch (LM.getKind()) {
686 return Ctx.AccumTy;
688 return Ctx.ShortAccumTy;
690 return Ctx.LongAccumTy;
691 default:
692 return ArgType::Invalid();
693 }
694 case ConversionSpecifier::KArg:
695 switch (LM.getKind()) {
697 return Ctx.UnsignedAccumTy;
699 return Ctx.UnsignedShortAccumTy;
701 return Ctx.UnsignedLongAccumTy;
702 default:
703 return ArgType::Invalid();
704 }
705 case ConversionSpecifier::rArg:
706 switch (LM.getKind()) {
708 return Ctx.FractTy;
710 return Ctx.ShortFractTy;
712 return Ctx.LongFractTy;
713 default:
714 return ArgType::Invalid();
715 }
716 case ConversionSpecifier::RArg:
717 switch (LM.getKind()) {
719 return Ctx.UnsignedFractTy;
721 return Ctx.UnsignedShortFractTy;
723 return Ctx.UnsignedLongFractTy;
724 default:
725 return ArgType::Invalid();
726 }
727 default:
728 break;
729 }
730
731 // FIXME: Handle other cases.
732 return ArgType();
733}
734
735
737 bool IsObjCLiteral) const {
739
741 return ArgType::Invalid();
742
743 ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
744 if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
745 return ScalarTy;
746
747 return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
748}
749
751 ASTContext &Ctx, bool IsObjCLiteral) {
752 // %n is different from other conversion specifiers; don't try to fix it.
753 if (CS.getKind() == ConversionSpecifier::nArg)
754 return false;
755
756 // Handle Objective-C objects first. Note that while the '%@' specifier will
757 // not warn for structure pointer or void pointer arguments (because that's
758 // how CoreFoundation objects are implemented), we only show a fixit for '%@'
759 // if we know it's an object (block, id, class, or __attribute__((NSObject))).
760 if (QT->isObjCRetainableType()) {
761 if (!IsObjCLiteral)
762 return false;
763
764 CS.setKind(ConversionSpecifier::ObjCObjArg);
765
766 // Disable irrelevant flags
767 HasThousandsGrouping = false;
768 HasPlusPrefix = false;
769 HasSpacePrefix = false;
770 HasAlternativeForm = false;
771 HasLeadingZeroes = false;
774
775 return true;
776 }
777
778 // Handle strings next (char *, wchar_t *)
779 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
780 CS.setKind(ConversionSpecifier::sArg);
781
782 // Disable irrelevant flags
783 HasAlternativeForm = false;
784 HasLeadingZeroes = false;
785
786 // Set the long length modifier for wide characters
787 if (QT->getPointeeType()->isWideCharType())
789 else
791
792 return true;
793 }
794
795 // If it's an enum, get its underlying type.
796 if (const auto *ED = QT->getAsEnumDecl())
797 QT = ED->getIntegerType();
798
799 const BuiltinType *BT = QT->getAs<BuiltinType>();
800 if (!BT) {
801 const VectorType *VT = QT->getAs<VectorType>();
802 if (VT) {
803 QT = VT->getElementType();
804 BT = QT->getAs<BuiltinType>();
806 }
807 }
808
809 // We can only work with builtin types.
810 if (!BT)
811 return false;
812
813 // Set length modifier
814 switch (BT->getKind()) {
815 case BuiltinType::Bool:
816 case BuiltinType::WChar_U:
817 case BuiltinType::WChar_S:
818 case BuiltinType::Char8: // FIXME: Treat like 'char'?
819 case BuiltinType::Char16:
820 case BuiltinType::Char32:
821 case BuiltinType::UInt128:
822 case BuiltinType::Int128:
823 case BuiltinType::Half:
824 case BuiltinType::BFloat16:
825 case BuiltinType::Float16:
826 case BuiltinType::Float128:
827 case BuiltinType::Ibm128:
828 case BuiltinType::ShortAccum:
829 case BuiltinType::Accum:
830 case BuiltinType::LongAccum:
831 case BuiltinType::UShortAccum:
832 case BuiltinType::UAccum:
833 case BuiltinType::ULongAccum:
834 case BuiltinType::ShortFract:
835 case BuiltinType::Fract:
836 case BuiltinType::LongFract:
837 case BuiltinType::UShortFract:
838 case BuiltinType::UFract:
839 case BuiltinType::ULongFract:
840 case BuiltinType::SatShortAccum:
841 case BuiltinType::SatAccum:
842 case BuiltinType::SatLongAccum:
843 case BuiltinType::SatUShortAccum:
844 case BuiltinType::SatUAccum:
845 case BuiltinType::SatULongAccum:
846 case BuiltinType::SatShortFract:
847 case BuiltinType::SatFract:
848 case BuiltinType::SatLongFract:
849 case BuiltinType::SatUShortFract:
850 case BuiltinType::SatUFract:
851 case BuiltinType::SatULongFract:
852 // Various types which are non-trivial to correct.
853 return false;
854
855#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
856 case BuiltinType::Id:
857#include "clang/Basic/OpenCLImageTypes.def"
858#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
859 case BuiltinType::Id:
860#include "clang/Basic/OpenCLExtensionTypes.def"
861#define SVE_TYPE(Name, Id, SingletonId) \
862 case BuiltinType::Id:
863#include "clang/Basic/AArch64ACLETypes.def"
864#define PPC_VECTOR_TYPE(Name, Id, Size) \
865 case BuiltinType::Id:
866#include "clang/Basic/PPCTypes.def"
867#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
868#include "clang/Basic/RISCVVTypes.def"
869#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
870#include "clang/Basic/WebAssemblyReferenceTypes.def"
871#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
872#include "clang/Basic/AMDGPUTypes.def"
873#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
874#include "clang/Basic/HLSLIntangibleTypes.def"
875#define SIGNED_TYPE(Id, SingletonId)
876#define UNSIGNED_TYPE(Id, SingletonId)
877#define FLOATING_TYPE(Id, SingletonId)
878#define BUILTIN_TYPE(Id, SingletonId) \
879 case BuiltinType::Id:
880#include "clang/AST/BuiltinTypes.def"
881 // Misc other stuff which doesn't make sense here.
882 return false;
883
884 case BuiltinType::UInt:
885 case BuiltinType::Int:
886 case BuiltinType::Float:
889 break;
890 case BuiltinType::Double:
893 break;
894 case BuiltinType::Char_U:
895 case BuiltinType::UChar:
896 case BuiltinType::Char_S:
897 case BuiltinType::SChar:
899 break;
900
901 case BuiltinType::Short:
902 case BuiltinType::UShort:
904 break;
905
906 case BuiltinType::Long:
907 case BuiltinType::ULong:
909 break;
910
911 case BuiltinType::LongLong:
912 case BuiltinType::ULongLong:
914 break;
915
916 case BuiltinType::LongDouble:
918 break;
919 }
920
921 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
922 if (LangOpt.C99 || LangOpt.CPlusPlus11)
924
925 // If fixing the length modifier was enough, we might be done.
926 if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
927 // If we're going to offer a fix anyway, make sure the sign matches.
928 switch (CS.getKind()) {
929 case ConversionSpecifier::uArg:
930 case ConversionSpecifier::UArg:
931 if (QT->isSignedIntegerType())
933 break;
934 case ConversionSpecifier::dArg:
935 case ConversionSpecifier::DArg:
936 case ConversionSpecifier::iArg:
937 if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
939 break;
940 default:
941 // Other specifiers do not have signed/unsigned variants.
942 break;
943 }
944
945 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
946 if (ATR.isValid() && ATR.matchesType(Ctx, QT))
947 return true;
948 }
949
950 // Set conversion specifier and disable any flags which do not apply to it.
951 // Let typedefs to char fall through to int, as %c is silly for uint8_t.
952 if (!QT->getAs<TypedefType>() && QT->isCharType()) {
953 CS.setKind(ConversionSpecifier::cArg);
956 HasAlternativeForm = false;
957 HasLeadingZeroes = false;
958 HasPlusPrefix = false;
959 }
960 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
961 else if (QT->isRealFloatingType()) {
962 CS.setKind(ConversionSpecifier::fArg);
963 } else if (QT->isSignedIntegerType()) {
964 CS.setKind(ConversionSpecifier::dArg);
965 HasAlternativeForm = false;
966 } else if (QT->isUnsignedIntegerType()) {
967 CS.setKind(ConversionSpecifier::uArg);
968 HasAlternativeForm = false;
969 HasPlusPrefix = false;
970 } else {
971 llvm_unreachable("Unexpected type");
972 }
973
974 return true;
975}
976
977void PrintfSpecifier::toString(raw_ostream &os) const {
978 // Whilst some features have no defined order, we are using the order
979 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
980 os << "%";
981
982 // Positional args
983 if (usesPositionalArg()) {
984 os << getPositionalArgIndex() << "$";
985 }
986
987 // Conversion flags
988 if (IsLeftJustified) os << "-";
989 if (HasPlusPrefix) os << "+";
990 if (HasSpacePrefix) os << " ";
991 if (HasAlternativeForm) os << "#";
992 if (HasLeadingZeroes) os << "0";
993
994 // Minimum field width
996 // Precision
997 Precision.toString(os);
998
999 // Vector modifier
1000 if (!VectorNumElts.isInvalid())
1001 os << 'v' << VectorNumElts.getConstantAmount();
1002
1003 // Length modifier
1004 os << LM.toString();
1005 // Conversion specifier
1006 os << CS.toString();
1007}
1008
1010 if (!HasPlusPrefix)
1011 return true;
1012
1013 // The plus prefix only makes sense for signed conversions
1014 switch (CS.getKind()) {
1015 case ConversionSpecifier::dArg:
1016 case ConversionSpecifier::DArg:
1017 case ConversionSpecifier::iArg:
1018 case ConversionSpecifier::fArg:
1019 case ConversionSpecifier::FArg:
1020 case ConversionSpecifier::eArg:
1021 case ConversionSpecifier::EArg:
1022 case ConversionSpecifier::gArg:
1023 case ConversionSpecifier::GArg:
1024 case ConversionSpecifier::aArg:
1025 case ConversionSpecifier::AArg:
1026 case ConversionSpecifier::FreeBSDrArg:
1027 case ConversionSpecifier::FreeBSDyArg:
1028 case ConversionSpecifier::rArg:
1029 case ConversionSpecifier::kArg:
1030 return true;
1031
1032 default:
1033 return false;
1034 }
1035}
1036
1038 if (!HasAlternativeForm)
1039 return true;
1040
1041 // Alternate form flag only valid with the bBoxXaAeEfFgGrRkK conversions
1042 switch (CS.getKind()) {
1043 case ConversionSpecifier::bArg:
1044 case ConversionSpecifier::BArg:
1045 case ConversionSpecifier::oArg:
1046 case ConversionSpecifier::OArg:
1047 case ConversionSpecifier::xArg:
1048 case ConversionSpecifier::XArg:
1049 case ConversionSpecifier::aArg:
1050 case ConversionSpecifier::AArg:
1051 case ConversionSpecifier::eArg:
1052 case ConversionSpecifier::EArg:
1053 case ConversionSpecifier::fArg:
1054 case ConversionSpecifier::FArg:
1055 case ConversionSpecifier::gArg:
1056 case ConversionSpecifier::GArg:
1057 case ConversionSpecifier::FreeBSDrArg:
1058 case ConversionSpecifier::FreeBSDyArg:
1059 case ConversionSpecifier::rArg:
1060 case ConversionSpecifier::RArg:
1061 case ConversionSpecifier::kArg:
1062 case ConversionSpecifier::KArg:
1063 return true;
1064
1065 default:
1066 return false;
1067 }
1068}
1069
1071 if (!HasLeadingZeroes)
1072 return true;
1073
1074 // Leading zeroes flag only valid with the bBdiouxXaAeEfFgGrRkK conversions
1075 switch (CS.getKind()) {
1076 case ConversionSpecifier::bArg:
1077 case ConversionSpecifier::BArg:
1078 case ConversionSpecifier::dArg:
1079 case ConversionSpecifier::DArg:
1080 case ConversionSpecifier::iArg:
1081 case ConversionSpecifier::oArg:
1082 case ConversionSpecifier::OArg:
1083 case ConversionSpecifier::uArg:
1084 case ConversionSpecifier::UArg:
1085 case ConversionSpecifier::xArg:
1086 case ConversionSpecifier::XArg:
1087 case ConversionSpecifier::aArg:
1088 case ConversionSpecifier::AArg:
1089 case ConversionSpecifier::eArg:
1090 case ConversionSpecifier::EArg:
1091 case ConversionSpecifier::fArg:
1092 case ConversionSpecifier::FArg:
1093 case ConversionSpecifier::gArg:
1094 case ConversionSpecifier::GArg:
1095 case ConversionSpecifier::FreeBSDrArg:
1096 case ConversionSpecifier::FreeBSDyArg:
1097 case ConversionSpecifier::rArg:
1098 case ConversionSpecifier::RArg:
1099 case ConversionSpecifier::kArg:
1100 case ConversionSpecifier::KArg:
1101 return true;
1102
1103 default:
1104 return false;
1105 }
1106}
1107
1109 if (!HasSpacePrefix)
1110 return true;
1111
1112 // The space prefix only makes sense for signed conversions
1113 switch (CS.getKind()) {
1114 case ConversionSpecifier::dArg:
1115 case ConversionSpecifier::DArg:
1116 case ConversionSpecifier::iArg:
1117 case ConversionSpecifier::fArg:
1118 case ConversionSpecifier::FArg:
1119 case ConversionSpecifier::eArg:
1120 case ConversionSpecifier::EArg:
1121 case ConversionSpecifier::gArg:
1122 case ConversionSpecifier::GArg:
1123 case ConversionSpecifier::aArg:
1124 case ConversionSpecifier::AArg:
1125 case ConversionSpecifier::FreeBSDrArg:
1126 case ConversionSpecifier::FreeBSDyArg:
1127 case ConversionSpecifier::rArg:
1128 case ConversionSpecifier::kArg:
1129 return true;
1130
1131 default:
1132 return false;
1133 }
1134}
1135
1137 if (!IsLeftJustified)
1138 return true;
1139
1140 // The left justified flag is valid for all conversions except n
1141 switch (CS.getKind()) {
1142 case ConversionSpecifier::nArg:
1143 return false;
1144
1145 default:
1146 return true;
1147 }
1148}
1149
1151 if (!HasThousandsGrouping)
1152 return true;
1153
1154 switch (CS.getKind()) {
1155 case ConversionSpecifier::dArg:
1156 case ConversionSpecifier::DArg:
1157 case ConversionSpecifier::iArg:
1158 case ConversionSpecifier::uArg:
1159 case ConversionSpecifier::UArg:
1160 case ConversionSpecifier::fArg:
1161 case ConversionSpecifier::FArg:
1162 case ConversionSpecifier::gArg:
1163 case ConversionSpecifier::GArg:
1164 return true;
1165 default:
1166 return false;
1167 }
1168}
1169
1172 return true;
1173
1174 // Precision is only valid with the bBdiouxXaAeEfFgGsPrRkK conversions
1175 switch (CS.getKind()) {
1176 case ConversionSpecifier::bArg:
1177 case ConversionSpecifier::BArg:
1178 case ConversionSpecifier::dArg:
1179 case ConversionSpecifier::DArg:
1180 case ConversionSpecifier::iArg:
1181 case ConversionSpecifier::oArg:
1182 case ConversionSpecifier::OArg:
1183 case ConversionSpecifier::uArg:
1184 case ConversionSpecifier::UArg:
1185 case ConversionSpecifier::xArg:
1186 case ConversionSpecifier::XArg:
1187 case ConversionSpecifier::aArg:
1188 case ConversionSpecifier::AArg:
1189 case ConversionSpecifier::eArg:
1190 case ConversionSpecifier::EArg:
1191 case ConversionSpecifier::fArg:
1192 case ConversionSpecifier::FArg:
1193 case ConversionSpecifier::gArg:
1194 case ConversionSpecifier::GArg:
1195 case ConversionSpecifier::sArg:
1196 case ConversionSpecifier::FreeBSDrArg:
1197 case ConversionSpecifier::FreeBSDyArg:
1198 case ConversionSpecifier::PArg:
1199 case ConversionSpecifier::rArg:
1200 case ConversionSpecifier::RArg:
1201 case ConversionSpecifier::kArg:
1202 case ConversionSpecifier::KArg:
1203 return true;
1204
1205 default:
1206 return false;
1207 }
1208}
1211 return true;
1212
1213 // The field width is valid for all conversions except n
1214 switch (CS.getKind()) {
1215 case ConversionSpecifier::nArg:
1216 return false;
1217
1218 default:
1219 return true;
1220 }
1221}
Expr * E
llvm::MachO::Target Target
Definition: MachO.h:51
clang::analyze_format_string::SpecifierResult< PrintfSpecifier > PrintfSpecifierResult
static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, const char *Start, const char *&Beg, const char *E, unsigned *argIndex)
static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, const char *&Beg, const char *E, unsigned &argIndex, const LangOptions &LO, const TargetInfo &Target, bool Warn, bool isFreeBSDKPrintf)
static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS, const char *FlagBeg, const char *E, bool Warn)
SourceLocation Begin
__device__ __2f16 float c
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
CanQualType AccumTy
Definition: ASTContext.h:1235
CanQualType LongTy
Definition: ASTContext.h:1231
CanQualType UnsignedShortAccumTy
Definition: ASTContext.h:1237
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
CanQualType ShortAccumTy
Definition: ASTContext.h:1235
CanQualType FloatTy
Definition: ASTContext.h:1234
CanQualType DoubleTy
Definition: ASTContext.h:1234
CanQualType getIntMaxType() const
Return the unique type for "intmax_t" (C99 7.18.1.5), defined in <stdint.h>.
CanQualType LongDoubleTy
Definition: ASTContext.h:1234
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType UnsignedLongFractTy
Definition: ASTContext.h:1239
CanQualType WideCharTy
Definition: ASTContext.h:1226
const LangOptions & getLangOpts() const
Definition: ASTContext.h:894
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
CanQualType UnsignedFractTy
Definition: ASTContext.h:1239
CanQualType UnsignedLongTy
Definition: ASTContext.h:1232
CanQualType UnsignedLongAccumTy
Definition: ASTContext.h:1237
CanQualType ShortFractTy
Definition: ASTContext.h:1238
CanQualType IntTy
Definition: ASTContext.h:1231
CanQualType SignedCharTy
Definition: ASTContext.h:1231
CanQualType UnsignedCharTy
Definition: ASTContext.h:1232
CanQualType UnsignedShortFractTy
Definition: ASTContext.h:1239
CanQualType UnsignedIntTy
Definition: ASTContext.h:1232
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:1233
CanQualType UnsignedShortTy
Definition: ASTContext.h:1232
CanQualType ShortTy
Definition: ASTContext.h:1231
CanQualType FractTy
Definition: ASTContext.h:1238
CanQualType LongAccumTy
Definition: ASTContext.h:1236
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:859
CanQualType LongFractTy
Definition: ASTContext.h:1238
QualType getSignedSizeType() const
Return the unique signed counterpart of the integer type corresponding to size_t.
CanQualType LongLongTy
Definition: ASTContext.h:1231
CanQualType getUIntMaxType() const
Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in <stdint.h>.
CanQualType HalfTy
Definition: ASTContext.h:1246
CanQualType UnsignedAccumTy
Definition: ASTContext.h:1237
This class is used for builtin types like 'int'.
Definition: TypeBase.h:3182
Kind getKind() const
Definition: TypeBase.h:3230
QualType withConst() const
Retrieves a version of this type with const applied.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:434
A (possibly-)qualified type.
Definition: TypeBase.h:937
Exposes information about the current target.
Definition: TargetInfo.h:226
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1288
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition: Type.cpp:2209
bool isCharType() const
Definition: Type.cpp:2136
bool isPointerType() const
Definition: TypeBase.h:8580
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition: Type.cpp:2172
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition: Type.h:53
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2324
bool isWideCharType() const
Definition: Type.cpp:2145
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Definition: Type.cpp:2257
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool isObjCRetainableType() const
Definition: Type.cpp:5336
Represents a GCC generic vector type.
Definition: TypeBase.h:4191
unsigned getNumElements() const
Definition: TypeBase.h:4206
QualType getElementType() const
Definition: TypeBase.h:4205
static ArgType makePtrdiffT(const ArgType &A)
Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t type.
Definition: FormatString.h:334
static ArgType PtrTo(const ArgType &A)
Create an ArgType which corresponds to the type pointer to A.
Definition: FormatString.h:318
ArgType makeVectorType(ASTContext &C, unsigned NumElts) const
static ArgType makeSizeT(const ArgType &A)
Create an ArgType which corresponds to the size_t/ssize_t type.
Definition: FormatString.h:326
MatchKind matchesType(ASTContext &C, QualType argTy) const
static bool namedTypeToLengthModifier(ASTContext &Ctx, QualType QT, LengthModifier &LM)
For a TypedefType QT, if it is a named integer type such as size_t, assign the appropriate value to L...
bool hasValidLengthModifier(const TargetInfo &Target, const LangOptions &LO) const
virtual bool HandleInvalidPrintfConversionSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:746
virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart, const char *flagsEnd, const char *conversionPosition)
Definition: FormatString.h:741
virtual void HandleInvalidObjCModifierFlag(const char *startFlag, unsigned flagLen)
Definition: FormatString.h:738
virtual void HandleNullChar(const char *nullCharacter)
Definition: FormatString.h:723
virtual void handleInvalidMaskType(StringRef MaskType)
Handle mask types whose sizes are not between one and eight bytes.
Definition: FormatString.h:761
virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen, const TargetInfo &Target)
Definition: FormatString.h:753
virtual void HandleEmptyObjCModifierFlag(const char *startFlags, unsigned flagsLen)
Definition: FormatString.h:735
virtual void HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:732
Represents the length modifier in a format string in scanf/printf.
Definition: FormatString.h:65
bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx, bool IsObjCLiteral)
Changes the specifier and length according to a QualType, retaining any flags or options.
const PrintfConversionSpecifier & getConversionSpecifier() const
Definition: FormatString.h:586
ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const
Returns the builtin type that a data argument paired with this format specifier should have.
Defines the clang::TargetInfo interface.
Common components of both fprintf and fscanf format strings.
Definition: FormatString.h:30
bool parseFormatStringHasFormattingSpecifiers(const char *Begin, const char *End, const LangOptions &LO, const TargetInfo &Target)
Return true if the given string has at least one formatting specifier.
OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, unsigned &argIndex)
bool ParsePrintfString(FormatStringHandler &H, const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target, bool isFreeBSDKPrintf)
bool ParseFormatStringHasSArg(const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target)
Pieces specific to fprintf format strings.
Definition: FormatString.h:501
The JSON file list parser is used to communicate input to InstallAPI.
@ Match
This is not an overload because the signature exactly matches an existing declaration.