clang 23.0.0git
FormatString.cpp
Go to the documentation of this file.
1// FormatString.cpp - Common stuff for handling printf/scanf formats -*- 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// Shared details for processing format strings of printf and scanf
10// (and friends).
11//
12//===----------------------------------------------------------------------===//
13
14#include "FormatStringParsing.h"
17#include "llvm/ADT/StringExtras.h"
18#include "llvm/Support/ConvertUTF.h"
19#include <optional>
20
27using namespace clang;
28
29// Key function to FormatStringHandler.
31
32//===----------------------------------------------------------------------===//
33// Functions for parsing format strings components in both printf and
34// scanf format strings.
35//===----------------------------------------------------------------------===//
36
38 const char *E) {
39 const char *I = Beg;
40 UpdateOnReturn<const char *> UpdateBeg(Beg, I);
41
42 unsigned accumulator = 0;
43 bool hasDigits = false;
44
45 for (; I != E; ++I) {
46 char c = *I;
47 if (c >= '0' && c <= '9') {
48 hasDigits = true;
49 accumulator = (accumulator * 10) + (c - '0');
50 continue;
51 }
52
53 if (hasDigits)
54 return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
55 false);
56
57 break;
58 }
59
60 return OptionalAmount();
61}
62
63static bool ParseWidthModifier(const char *&I, const char *E,
64 unsigned &BitWidth, unsigned &ModifierLength) {
65 StringRef W = StringRef(I, E - I).take_while(llvm::isDigit);
66 if (W.empty() || W.front() == '0')
67 return false;
68
69 if (W.getAsInteger(10, BitWidth))
70 return false;
71
72 I = W.end();
73 ModifierLength += W.size();
74
75 return true;
76}
77
79 const char *&Beg, const char *E, unsigned &argIndex) {
80 if (*Beg == '*') {
81 ++Beg;
82 return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
83 }
84
85 return ParseAmount(Beg, E);
86}
87
89 FormatStringHandler &H, const char *Start, const char *&Beg, const char *E,
91 if (*Beg == '*') {
92 const char *I = Beg + 1;
93 const OptionalAmount &Amt = ParseAmount(I, E);
94
96 H.HandleInvalidPosition(Beg, I - Beg, p);
97 return OptionalAmount(false);
98 }
99
100 if (I == E) {
101 // No more characters left?
102 H.HandleIncompleteSpecifier(Start, E - Start);
103 return OptionalAmount(false);
104 }
105
107
108 if (*I == '$') {
109 // Handle positional arguments
110
111 // Special case: '*0$', since this is an easy mistake.
112 if (Amt.getConstantAmount() == 0) {
113 H.HandleZeroPosition(Beg, I - Beg + 1);
114 return OptionalAmount(false);
115 }
116
117 const char *Tmp = Beg;
118 Beg = ++I;
119
121 Tmp, 0, true);
122 }
123
124 H.HandleInvalidPosition(Beg, I - Beg, p);
125 return OptionalAmount(false);
126 }
127
128 return ParseAmount(Beg, E);
129}
130
132 FormatStringHandler &H, FormatSpecifier &CS, const char *Start,
133 const char *&Beg, const char *E, unsigned *argIndex) {
134 // FIXME: Support negative field widths.
135 if (argIndex) {
136 CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
137 } else {
139 H, Start, Beg, E, analyze_format_string::FieldWidthPos);
140
141 if (Amt.isInvalid())
142 return true;
143 CS.setFieldWidth(Amt);
144 }
145 return false;
146}
147
149 FormatSpecifier &FS,
150 const char *Start,
151 const char *&Beg,
152 const char *E) {
153 const char *I = Beg;
154
155 const OptionalAmount &Amt = ParseAmount(I, E);
156
157 if (I == E) {
158 // No more characters left?
159 H.HandleIncompleteSpecifier(Start, E - Start);
160 return true;
161 }
162
163 if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
164 // Warn that positional arguments are non-standard.
165 H.HandlePosition(Start, I - Start);
166
167 // Special case: '%0$', since this is an easy mistake.
168 if (Amt.getConstantAmount() == 0) {
169 H.HandleZeroPosition(Start, I - Start);
170 return true;
171 }
172
173 FS.setArgIndex(Amt.getConstantAmount() - 1);
175 // Update the caller's pointer if we decided to consume
176 // these characters.
177 Beg = I;
178 return false;
179 }
180
181 return false;
182}
183
185 FormatSpecifier &FS,
186 const char *&I,
187 const char *E,
188 const LangOptions &LO) {
189 if (!LO.OpenCL)
190 return false;
191
192 const char *Start = I;
193 if (*I == 'v') {
194 ++I;
195
196 if (I == E) {
197 H.HandleIncompleteSpecifier(Start, E - Start);
198 return true;
199 }
200
201 OptionalAmount NumElts = ParseAmount(I, E);
202 if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
203 H.HandleIncompleteSpecifier(Start, E - Start);
204 return true;
205 }
206
207 FS.setVectorNumElts(NumElts);
208 }
209
210 return false;
211}
212
214 const char *&I,
215 const char *E,
216 const LangOptions &LO,
217 bool IsScanf) {
219 const char *lmPosition = I;
220 switch (*I) {
221 default:
222 return false;
223 case 'h':
224 ++I;
225 if (I != E && *I == 'h') {
226 ++I;
227 lmKind = LengthModifier::AsChar;
228 } else if (I != E && *I == 'l' && LO.OpenCL) {
229 ++I;
231 } else {
233 }
234 break;
235 case 'l':
236 ++I;
237 if (I != E && *I == 'l') {
238 ++I;
240 } else {
241 lmKind = LengthModifier::AsLong;
242 }
243 break;
244 case 'j':
246 ++I;
247 break;
248 case 'z':
250 ++I;
251 break;
252 case 't':
254 ++I;
255 break;
256 case 'L':
258 ++I;
259 break;
260 case 'q':
261 lmKind = LengthModifier::AsQuad;
262 ++I;
263 break;
264 case 'a':
265 if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
266 // For scanf in C90, look at the next character to see if this should
267 // be parsed as the GNU extension 'a' length modifier. If not, this
268 // will be parsed as a conversion specifier.
269 ++I;
270 if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
272 break;
273 }
274 --I;
275 }
276 return false;
277 case 'm':
278 if (IsScanf) {
280 ++I;
281 break;
282 }
283 return false;
284 // printf: AsInt64, AsInt32, AsInt3264
285 // scanf: AsInt64
286 case 'I':
287 if (I + 1 != E && I + 2 != E) {
288 if (I[1] == '6' && I[2] == '4') {
289 I += 3;
291 break;
292 }
293 if (IsScanf)
294 return false;
295
296 if (I[1] == '3' && I[2] == '2') {
297 I += 3;
299 break;
300 }
301 }
302 ++I;
304 break;
305 case 'H':
306 if (LO.C23) {
308 ++I;
309 break;
310 }
311 return false;
312 case 'D':
313 if (LO.C23) {
314 ++I;
315 if (I != E && *I == 'D') {
316 ++I;
318 } else {
320 }
321 break;
322 }
323 return false;
324 case 'w':
325 if (LO.C23) {
326 const char *WidthModifier = I + 1;
327 unsigned BitWidth = 0;
328 unsigned ModifierLength = 1;
329
331 if (WidthModifier != E && *WidthModifier == 'f') {
332 WidthModifier = I + 2;
333 ModifierLength = 2;
334 WidthKind = LengthModifier::AsFastIntN;
335 }
336
337 if (ParseWidthModifier(WidthModifier, E, BitWidth, ModifierLength)) {
338 I = WidthModifier;
340 LengthModifier(lmPosition, WidthKind, BitWidth, ModifierLength));
341 return true;
342 }
343 }
344 lmKind = LengthModifier::AsWide;
345 ++I;
346 break;
347 }
348 LengthModifier lm(lmPosition, lmKind);
349 FS.setLengthModifier(lm);
350 return true;
351}
352
354 const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
355 if (SpecifierBegin + 1 >= FmtStrEnd)
356 return false;
357
358 const llvm::UTF8 *SB =
359 reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
360 const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
361 const char FirstByte = *SB;
362
363 // If the invalid specifier is a multibyte UTF-8 string, return the
364 // total length accordingly so that the conversion specifier can be
365 // properly updated to reflect a complete UTF-8 specifier.
366 unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
367 if (NumBytes == 1)
368 return false;
369 if (SB + NumBytes > SE)
370 return false;
371
372 Len = NumBytes + 1;
373 return true;
374}
375
376//===----------------------------------------------------------------------===//
377// Methods on ArgType.
378//===----------------------------------------------------------------------===//
379
382 if (!Ctx.getLangOpts().C99 && !Ctx.getLangOpts().CPlusPlus)
383 return false;
384 for (/**/; const auto *TT = QT->getAs<TypedefType>(); QT = TT->desugar()) {
385 const auto *TD = TT->getDecl();
386 const auto *DC = TT->getDecl()->getDeclContext();
387 if (DC->isTranslationUnit() || DC->isStdNamespace()) {
388 StringRef Name = TD->getIdentifier()->getName();
389 if (Name == "size_t") {
391 return true;
392 } else if (Name == "ssize_t" /*Not C99, but common in Unix.*/) {
394 return true;
395 } else if (Name == "ptrdiff_t") {
397 return true;
398 } else if (Name == "intmax_t") {
400 return true;
401 } else if (Name == "uintmax_t") {
403 return true;
404 }
405 }
406 }
407 if (const auto *PST = QT->getAs<PredefinedSugarType>()) {
408 using Kind = PredefinedSugarType::Kind;
409 switch (PST->getKind()) {
410 case Kind::SizeT:
411 case Kind::SignedSizeT:
413 return true;
414 case Kind::PtrdiffT:
416 return true;
417 }
418 llvm_unreachable("unexpected kind");
419 }
420 return false;
421}
422
423// Check whether T and E are compatible size_t/ptrdiff_t types. E must be
424// consistent with LE.
425// T is the type of the actual expression in the code to be checked, and E is
426// the expected type parsed from the format string.
430
431 if (!T->isIntegerType() || T->isBooleanType())
432 return MatchKind::NoMatch;
433
434 if (C.hasSameType(T, E))
435 return MatchKind::Match;
436
437 if (C.getCorrespondingSignedType(T.getCanonicalType()) !=
438 C.getCorrespondingSignedType(E.getCanonicalType()))
439 return MatchKind::NoMatch;
440
441 return MatchKind::NoMatchSignedness;
442}
443
446 // When using the format attribute in C++, you can receive a function or an
447 // array that will necessarily decay to a pointer when passed to the final
448 // format consumer. Apply decay before type comparison.
449 if (argTy->canDecayToPointerType())
450 argTy = C.getDecayedType(argTy);
451
452 if (Ptr) {
453 // It has to be a pointer.
454 const PointerType *PT = argTy->getAs<PointerType>();
455 if (!PT)
456 return NoMatch;
457
458 // We cannot write through a const qualified pointer.
460 return NoMatch;
461
462 argTy = PT->getPointeeType();
463 }
464
465 if (const auto *OBT = argTy->getAs<OverflowBehaviorType>())
466 argTy = OBT->getUnderlyingType();
467
468 switch (K) {
469 case InvalidTy:
470 llvm_unreachable("ArgType must be valid");
471
472 case UnsupportedTy:
473 return NoMatch;
474
475 case UnknownTy:
476 return Match;
477
478 case AnyCharTy: {
479 if (const auto *ED = argTy->getAsEnumDecl()) {
480 // If the enum is incomplete we know nothing about the underlying type.
481 // Assume that it's 'int'. Do not use the underlying type for a scoped
482 // enumeration.
483 if (!ED->isComplete())
484 return NoMatch;
485 if (!ED->isScoped())
486 argTy = ED->getIntegerType();
487 }
488
489 if (const auto *BT = argTy->getAs<BuiltinType>()) {
490 // The types are perfectly matched?
491 switch (BT->getKind()) {
492 default:
493 break;
494 case BuiltinType::Char_S:
495 case BuiltinType::SChar:
496 case BuiltinType::UChar:
497 case BuiltinType::Char_U:
498 return Match;
499 case BuiltinType::Bool:
500 if (!Ptr)
501 return Match;
502 break;
503 }
504 // "Partially matched" because of promotions?
505 if (!Ptr) {
506 switch (BT->getKind()) {
507 default:
508 break;
509 case BuiltinType::Int:
510 case BuiltinType::UInt:
511 return MatchPromotion;
512 case BuiltinType::Short:
513 case BuiltinType::UShort:
514 case BuiltinType::WChar_S:
515 case BuiltinType::WChar_U:
517 }
518 }
519 }
520 return NoMatch;
521 }
522
523 case SpecificTy: {
524 if (TK == TypeKind::SizeT || TK == TypeKind::PtrdiffT) {
525 return matchesSizeTPtrdiffT(C, argTy, T);
526 }
527
528 if (const auto *ED = argTy->getAsEnumDecl()) {
529 // If the enum is incomplete we know nothing about the underlying type.
530 // Assume that it's 'int'. Do not use the underlying type for a scoped
531 // enumeration as that needs an exact match.
532 if (!ED->isComplete())
533 argTy = C.IntTy;
534 else if (!ED->isScoped())
535 argTy = ED->getIntegerType();
536 }
537
538 if (argTy->isSaturatedFixedPointType())
539 argTy = C.getCorrespondingUnsaturatedType(argTy);
540
541 argTy = C.getCanonicalType(argTy).getUnqualifiedType();
542
543 if (T == argTy)
544 return Match;
545 if (const auto *BT = argTy->getAs<BuiltinType>()) {
546 // Check if the only difference between them is signed vs unsigned
547 // if true, return match signedness.
548 switch (BT->getKind()) {
549 default:
550 break;
551 case BuiltinType::Bool:
552 if (Ptr && (T == C.UnsignedCharTy || T == C.SignedCharTy))
553 return NoMatch;
554 [[fallthrough]];
555 case BuiltinType::Char_S:
556 case BuiltinType::SChar:
557 if (T == C.UnsignedShortTy || T == C.ShortTy)
559 if (T == C.UnsignedCharTy)
560 return NoMatchSignedness;
561 if (T == C.SignedCharTy)
562 return Match;
563 break;
564 case BuiltinType::Char_U:
565 case BuiltinType::UChar:
566 if (T == C.UnsignedShortTy || T == C.ShortTy)
568 if (T == C.UnsignedCharTy)
569 return Match;
570 if (T == C.SignedCharTy)
571 return NoMatchSignedness;
572 break;
573 case BuiltinType::Short:
574 if (T == C.UnsignedShortTy)
575 return NoMatchSignedness;
576 break;
577 case BuiltinType::UShort:
578 if (T == C.ShortTy)
579 return NoMatchSignedness;
580 break;
581 case BuiltinType::Int:
582 if (T == C.UnsignedIntTy)
583 return NoMatchSignedness;
584 break;
585 case BuiltinType::UInt:
586 if (T == C.IntTy)
587 return NoMatchSignedness;
588 break;
589 case BuiltinType::Long:
590 if (T == C.UnsignedLongTy)
591 return NoMatchSignedness;
592 break;
593 case BuiltinType::ULong:
594 if (T == C.LongTy)
595 return NoMatchSignedness;
596 break;
597 case BuiltinType::LongLong:
598 if (T == C.UnsignedLongLongTy)
599 return NoMatchSignedness;
600 break;
601 case BuiltinType::ULongLong:
602 if (T == C.LongLongTy)
603 return NoMatchSignedness;
604 break;
605 }
606 // "Partially matched" because of promotions?
607 if (!Ptr) {
608 switch (BT->getKind()) {
609 default:
610 break;
611 case BuiltinType::Bool:
612 if (T == C.IntTy || T == C.UnsignedIntTy)
613 return MatchPromotion;
614 break;
615 case BuiltinType::Int:
616 case BuiltinType::UInt:
617 if (T == C.SignedCharTy || T == C.UnsignedCharTy || T == C.ShortTy ||
618 T == C.UnsignedShortTy || T == C.WCharTy || T == C.WideCharTy)
619 return MatchPromotion;
620 break;
621 case BuiltinType::Char_U:
622 if (T == C.UnsignedIntTy)
623 return MatchPromotion;
624 if (T == C.UnsignedShortTy)
626 break;
627 case BuiltinType::Char_S:
628 if (T == C.IntTy)
629 return MatchPromotion;
630 if (T == C.ShortTy)
632 break;
633 case BuiltinType::Half:
634 case BuiltinType::Float:
635 if (T == C.DoubleTy)
636 return MatchPromotion;
637 break;
638 case BuiltinType::Short:
639 case BuiltinType::UShort:
640 if (T == C.SignedCharTy || T == C.UnsignedCharTy)
642 break;
643 case BuiltinType::WChar_U:
644 case BuiltinType::WChar_S:
645 if (T != C.WCharTy && T != C.WideCharTy)
647 }
648 }
649 }
650 return NoMatch;
651 }
652
653 case CStrTy:
654 if (const auto *PT = argTy->getAs<PointerType>();
655 PT && PT->getPointeeType()->isCharType())
656 return Match;
657 return NoMatch;
658
659 case WCStrTy:
660 if (const auto *PT = argTy->getAs<PointerType>();
661 PT &&
662 C.hasSameUnqualifiedType(PT->getPointeeType(), C.getWideCharType()))
663 return Match;
664 return NoMatch;
665
666 case WIntTy: {
667 QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
668
669 if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)
670 return Match;
671
672 QualType PromoArg = C.isPromotableIntegerType(argTy)
673 ? C.getPromotedIntegerType(argTy)
674 : argTy;
675 PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
676
677 // If the promoted argument is the corresponding signed type of the
678 // wint_t type, then it should match.
679 if (PromoArg->hasSignedIntegerRepresentation() &&
680 C.getCorrespondingUnsignedType(PromoArg) == WInt)
681 return Match;
682
683 return WInt == PromoArg ? Match : NoMatch;
684 }
685
686 case CPointerTy:
687 if (const auto *PT = argTy->getAs<PointerType>()) {
688 QualType PointeeTy = PT->getPointeeType();
689 if (PointeeTy->isVoidType() || (!Ptr && PointeeTy->isCharType()))
690 return Match;
691 return NoMatchPedantic;
692 }
693
694 // nullptr_t* is not a double pointer, so reject when something like
695 // void** is expected.
696 // In C++, nullptr is promoted to void*. In C23, va_arg(ap, void*) is not
697 // undefined when the next argument is of type nullptr_t.
698 if (!Ptr && argTy->isNullPtrType())
699 return C.getLangOpts().CPlusPlus ? MatchPromotion : Match;
700
701 if (argTy->isObjCObjectPointerType() || argTy->isBlockPointerType())
702 return NoMatchPedantic;
703
704 return NoMatch;
705
706 case ObjCPointerTy: {
707 if (argTy->getAs<ObjCObjectPointerType>() ||
708 argTy->getAs<BlockPointerType>())
709 return Match;
710
711 // Handle implicit toll-free bridging.
712 if (const PointerType *PT = argTy->getAs<PointerType>()) {
713 // Things such as CFTypeRef are really just opaque pointers
714 // to C structs representing CF types that can often be bridged
715 // to Objective-C objects. Since the compiler doesn't know which
716 // structs can be toll-free bridged, we just accept them all.
717 QualType pointee = PT->getPointeeType();
718 if (pointee->isStructureType() || pointee->isVoidType())
719 return Match;
720 }
721 return NoMatch;
722 }
723 }
724
725 llvm_unreachable("Invalid ArgType Kind!");
726}
727
731
732 uint64_t IntSize = C.getTypeSize(C.IntTy);
733 uint64_t ASize = C.getTypeSize(A);
734 uint64_t BSize = C.getTypeSize(B);
735 if (std::max(ASize, IntSize) != std::max(BSize, IntSize))
736 return MK::NoMatch;
737 if (CheckSign && A->isSignedIntegerType() != B->isSignedIntegerType())
738 return MK::NoMatchSignedness;
739 if (ASize != BSize)
740 return MK::MatchPromotion;
741 return MK::Match;
742}
743
747
748 // Per matchesType.
749 if (K == AK::InvalidTy || Other.K == AK::InvalidTy)
750 return NoMatch;
751 if (K == AK::UnsupportedTy || Other.K == AK::UnsupportedTy)
752 return NoMatch;
753 if (K == AK::UnknownTy || Other.K == AK::UnknownTy)
754 return Match;
755
756 // Handle whether either (or both, or neither) sides has Ptr set,
757 // in addition to whether either (or both, or neither) sides is a SpecificTy
758 // that is a pointer.
759 ArgType Left = *this;
760 bool LeftWasPointer = false;
761 ArgType Right = Other;
762 bool RightWasPointer = false;
763 if (Left.Ptr) {
764 Left.Ptr = false;
765 LeftWasPointer = true;
766 } else if (Left.K == AK::SpecificTy && Left.T->isPointerType()) {
767 Left.T = Left.T->getPointeeType();
768 LeftWasPointer = true;
769 }
770 if (Right.Ptr) {
771 Right.Ptr = false;
772 RightWasPointer = true;
773 } else if (Right.K == AK::SpecificTy && Right.T->isPointerType()) {
774 Right.T = Right.T->getPointeeType();
775 RightWasPointer = true;
776 }
777
778 if (LeftWasPointer != RightWasPointer)
779 return NoMatch;
780
781 // Ensure that if at least one side is a SpecificTy, then Left is a
782 // SpecificTy.
783 if (Right.K == AK::SpecificTy)
784 std::swap(Left, Right);
785
786 if (Left.K == AK::SpecificTy) {
787 if (Right.K == AK::SpecificTy) {
788 if (Left.TK != TypeKind::DontCare) {
789 return matchesSizeTPtrdiffT(C, Right.T, Left.T);
790 } else if (Right.TK != TypeKind::DontCare) {
791 return matchesSizeTPtrdiffT(C, Left.T, Right.T);
792 }
793
794 auto Canon1 = C.getCanonicalType(Left.T);
795 auto Canon2 = C.getCanonicalType(Right.T);
796 if (Canon1 == Canon2)
797 return Match;
798
799 auto *BT1 = QualType(Canon1)->getAs<BuiltinType>();
800 auto *BT2 = QualType(Canon2)->getAs<BuiltinType>();
801 if (BT1 == nullptr || BT2 == nullptr)
802 return NoMatch;
803 if (BT1 == BT2)
804 return Match;
805
806 if (!LeftWasPointer && BT1->isInteger() && BT2->isInteger())
807 return integerTypeMatch(C, Canon1, Canon2, true);
808 return NoMatch;
809 } else if (Right.K == AK::AnyCharTy) {
810 if (!LeftWasPointer && Left.T->isIntegerType())
811 return integerTypeMatch(C, Left.T, C.CharTy, false);
812 return NoMatch;
813 } else if (Right.K == AK::WIntTy) {
814 if (!LeftWasPointer && Left.T->isIntegerType())
815 return integerTypeMatch(C, Left.T, C.WIntTy, true);
816 return NoMatch;
817 }
818 // It's hypothetically possible to create an AK::SpecificTy ArgType
819 // that matches another kind of ArgType, but in practice Clang doesn't
820 // do that, so ignore that case.
821 return NoMatch;
822 }
823
824 return Left.K == Right.K ? Match : NoMatch;
825}
826
827ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
828 // Check for valid vector element types.
829 if (T.isNull())
830 return ArgType::Invalid();
831
832 QualType Vec = C.getExtVectorType(T, NumElts);
833 return ArgType(Vec, Name);
834}
835
837 bool Signed) {
838 bool IsFast = LengthMod.getKind() == LengthModifier::AsFastIntN;
839 QualType Ty =
840 IsFast ? Ctx.getLeastIntTypeForBitwidth(LengthMod.getBitWidth(), Signed)
841 : Ctx.getIntTypeForBitwidth(LengthMod.getBitWidth(), Signed);
842 if (Ty.isNull())
843 return ArgType::Invalid();
844
845 ArgType Res(Ty);
846 Res.TK = IsFast ? (Signed ? TypeKind::FastIntN : TypeKind::FastUIntN)
847 : (Signed ? TypeKind::IntN : TypeKind::UIntN);
848 Res.BitWidth = LengthMod.getBitWidth();
849 return Res;
850}
851
853 QualType Res;
854 switch (K) {
855 case InvalidTy:
856 llvm_unreachable("No representative type for Invalid ArgType");
857 case UnknownTy:
858 llvm_unreachable("No representative type for Unknown ArgType");
859 case UnsupportedTy:
860 llvm_unreachable("No representative type for Unsupported ArgType");
861 case AnyCharTy:
862 Res = C.CharTy;
863 break;
864 case SpecificTy:
865 if (TK == TypeKind::PtrdiffT || TK == TypeKind::SizeT)
866 // Using Name as name, so no need to show the uglified name.
867 Res = T->getCanonicalTypeInternal();
868 else
869 Res = T;
870 break;
871 case CStrTy:
872 Res = C.getPointerType(C.CharTy);
873 break;
874 case WCStrTy:
875 Res = C.getPointerType(C.getWideCharType());
876 break;
877 case ObjCPointerTy:
878 Res = C.ObjCBuiltinIdTy;
879 break;
880 case CPointerTy:
881 Res = C.VoidPtrTy;
882 break;
883 case WIntTy: {
884 Res = C.getWIntType();
885 break;
886 }
887 }
888
889 if (Ptr)
890 Res = C.getPointerType(Res);
891 return Res;
892}
893
895 std::string S;
896 if (K != UnsupportedTy)
897 S = getRepresentativeType(C).getAsString(C.getPrintingPolicy());
898
899 std::string Alias;
900 if (Name) {
901 // Use a specific name for this type, e.g. "size_t".
902 Alias = Name;
903 } else {
904 const char *Prefix = nullptr;
905 switch (TK) {
906 case TypeKind::IntN:
907 Prefix = "int";
908 break;
909 case TypeKind::UIntN:
910 Prefix = "uint";
911 break;
912 case TypeKind::FastIntN:
913 Prefix = "int_fast";
914 break;
915 case TypeKind::FastUIntN:
916 Prefix = "uint_fast";
917 break;
918 case TypeKind::DontCare:
919 case TypeKind::SizeT:
920 case TypeKind::PtrdiffT:
921 break;
922 }
923 if (Prefix) {
924 Alias = Prefix;
925 Alias += std::to_string(BitWidth);
926 Alias += "_t";
927 }
928 }
929 if (!Alias.empty()) {
930 if (Ptr) {
931 // If ArgType is actually a pointer to T, append an asterisk.
932 Alias += (Alias[Alias.size() - 1] == '*') ? "*" : " *";
933 }
934 // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
935 if (S == Alias)
936 Alias.clear();
937 }
938
939 if (Alias.empty())
940 return std::string("'") + S + "'";
941
942 return std::string("'") + Alias + "'" +
943 (K == UnsupportedTy ? "" : " (aka '" + S + "')");
944}
945
946//===----------------------------------------------------------------------===//
947// Methods on OptionalAmount.
948//===----------------------------------------------------------------------===//
949
954
955//===----------------------------------------------------------------------===//
956// Methods on LengthModifier.
957//===----------------------------------------------------------------------===//
958
960 switch (kind) {
961 case AsChar:
962 return "hh";
963 case AsShort:
964 return "h";
965 case AsShortLong:
966 return "hl";
967 case AsLong: // or AsWideChar
968 return "l";
969 case AsLongLong:
970 return "ll";
971 case AsQuad:
972 return "q";
973 case AsIntMax:
974 return "j";
975 case AsSizeT:
976 return "z";
977 case AsPtrDiff:
978 return "t";
979 case AsInt32:
980 return "I32";
981 case AsInt3264:
982 return "I";
983 case AsInt64:
984 return "I64";
985 case AsLongDouble:
986 return "L";
987 case AsDecimal32:
988 return "H";
989 case AsDecimal64:
990 return "D";
991 case AsDecimal128:
992 return "DD";
993 case AsIntN:
994 case AsFastIntN:
995 return StringRef(Position, getLength());
996 case AsAllocate:
997 return "a";
998 case AsMAllocate:
999 return "m";
1000 case AsWide:
1001 return "w";
1002 case None:
1003 return "";
1004 }
1005 llvm_unreachable("Invalid LengthModifier Kind!");
1006}
1007
1008//===----------------------------------------------------------------------===//
1009// Methods on ConversionSpecifier.
1010//===----------------------------------------------------------------------===//
1011
1013 switch (kind) {
1014 case bArg:
1015 return "b";
1016 case BArg:
1017 return "B";
1018 case dArg:
1019 return "d";
1020 case DArg:
1021 return "D";
1022 case iArg:
1023 return "i";
1024 case oArg:
1025 return "o";
1026 case OArg:
1027 return "O";
1028 case uArg:
1029 return "u";
1030 case UArg:
1031 return "U";
1032 case xArg:
1033 return "x";
1034 case XArg:
1035 return "X";
1036 case fArg:
1037 return "f";
1038 case FArg:
1039 return "F";
1040 case eArg:
1041 return "e";
1042 case EArg:
1043 return "E";
1044 case gArg:
1045 return "g";
1046 case GArg:
1047 return "G";
1048 case aArg:
1049 return "a";
1050 case AArg:
1051 return "A";
1052 case cArg:
1053 return "c";
1054 case sArg:
1055 return "s";
1056 case pArg:
1057 return "p";
1058 case PArg:
1059 return "P";
1060 case nArg:
1061 return "n";
1062 case PercentArg:
1063 return "%";
1064 case ScanListArg:
1065 return "[";
1066 case InvalidSpecifier:
1067 return nullptr;
1068
1069 // POSIX unicode extensions.
1070 case CArg:
1071 return "C";
1072 case SArg:
1073 return "S";
1074
1075 // Objective-C specific specifiers.
1076 case ObjCObjArg:
1077 return "@";
1078
1079 // FreeBSD kernel specific specifiers.
1080 case FreeBSDbArg:
1081 return "b";
1082 case FreeBSDDArg:
1083 return "D";
1084 case FreeBSDrArg:
1085 return "r";
1086 case FreeBSDyArg:
1087 return "y";
1088
1089 // GlibC specific specifiers.
1090 case PrintErrno:
1091 return "m";
1092
1093 // MS specific specifiers.
1094 case ZArg:
1095 return "Z";
1096
1097 // ISO/IEC TR 18037 (fixed-point) specific specifiers.
1098 case rArg:
1099 return "r";
1100 case RArg:
1101 return "R";
1102 case kArg:
1103 return "k";
1104 case KArg:
1105 return "K";
1106 }
1107 return nullptr;
1108}
1109
1110std::optional<ConversionSpecifier>
1113
1114 switch (getKind()) {
1115 default:
1116 return std::nullopt;
1117 case DArg:
1118 NewKind = dArg;
1119 break;
1120 case UArg:
1121 NewKind = uArg;
1122 break;
1123 case OArg:
1124 NewKind = oArg;
1125 break;
1126 }
1127
1128 ConversionSpecifier FixedCS(*this);
1129 FixedCS.setKind(NewKind);
1130 return FixedCS;
1131}
1132
1133//===----------------------------------------------------------------------===//
1134// Methods on OptionalAmount.
1135//===----------------------------------------------------------------------===//
1136
1137void OptionalAmount::toString(raw_ostream &os) const {
1138 switch (hs) {
1139 case Invalid:
1140 case NotSpecified:
1141 return;
1142 case Arg:
1143 if (UsesDotPrefix)
1144 os << ".";
1145 if (usesPositionalArg())
1146 os << "*" << getPositionalArgIndex() << "$";
1147 else
1148 os << "*";
1149 break;
1150 case Constant:
1151 if (UsesDotPrefix)
1152 os << ".";
1153 os << amt;
1154 break;
1155 }
1156}
1157
1159 const LangOptions &LO) const {
1160 switch (LM.getKind()) {
1162 return true;
1163
1164 // Handle most integer flags
1166 // Length modifier only applies to FP vectors.
1167 if (LO.OpenCL && CS.isDoubleArg())
1168 return !VectorNumElts.isInvalid();
1169
1170 if (CS.isFixedPointArg())
1171 return true;
1172
1173 if (Target.getTriple().isOSMSVCRT()) {
1174 switch (CS.getKind()) {
1180 return true;
1181 default:
1182 break;
1183 }
1184 }
1185 [[fallthrough]];
1192 switch (CS.getKind()) {
1205 return true;
1208 return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
1209 default:
1210 return false;
1211 }
1212
1214 return LO.OpenCL && !VectorNumElts.isInvalid();
1215
1216 // Handle 'l' flag
1217 case LengthModifier::AsLong: // or AsWideChar
1218 if (CS.isDoubleArg()) {
1219 // Invalid for OpenCL FP scalars.
1220 if (LO.OpenCL && VectorNumElts.isInvalid())
1221 return false;
1222 return true;
1223 }
1224
1225 if (CS.isFixedPointArg())
1226 return true;
1227
1228 switch (CS.getKind()) {
1245 return true;
1248 return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
1249 default:
1250 return false;
1251 }
1252
1254 switch (CS.getKind()) {
1263 return true;
1264 // GNU libc extension.
1271 return !Target.getTriple().isOSDarwin() &&
1272 !Target.getTriple().isOSWindows();
1273 default:
1274 return false;
1275 }
1276
1279 if (!LO.C23)
1280 return false;
1281
1282 TargetInfo::IntType TargetType =
1283 LM.getKind() == LengthModifier::AsIntN
1284 ? Target.getIntTypeByWidth(LM.getBitWidth(), /*IsSigned=*/true)
1285 : Target.getLeastIntTypeByWidth(LM.getBitWidth(),
1286 /*IsSigned=*/true);
1287 if (TargetType == TargetInfo::NoInt)
1288 return false;
1289
1290 switch (CS.getKind()) {
1300 return true;
1301 default:
1302 return false;
1303 }
1304 }
1305
1307 switch (CS.getKind()) {
1311 return true;
1312 default:
1313 return false;
1314 }
1315
1317 switch (CS.getKind()) {
1323 return true;
1324 default:
1325 return false;
1326 }
1330 switch (CS.getKind()) {
1337 return Target.getTriple().isOSMSVCRT();
1338 default:
1339 return false;
1340 }
1342 switch (CS.getKind()) {
1348 return Target.getTriple().isOSMSVCRT();
1349 default:
1350 return false;
1351 }
1352
1356 switch (CS.getKind()) {
1365 return LO.C23;
1366 default:
1367 return false;
1368 }
1369 }
1370 llvm_unreachable("Invalid LengthModifier Kind!");
1371}
1372
1374 switch (LM.getKind()) {
1389 return true;
1397 case LengthModifier::AsShortLong: // ???
1398 return false;
1399 }
1400 llvm_unreachable("Invalid LengthModifier Kind!");
1401}
1402
1404 const LangOptions &LangOpt) const {
1405 switch (CS.getKind()) {
1430 return true;
1433 return LangOpt.ObjC;
1444 return false;
1449 return LangOpt.FixedPoint;
1450 }
1451 llvm_unreachable("Invalid ConversionSpecifier Kind!");
1452}
1453
1455 if (LM.getKind() == LengthModifier::AsLongDouble) {
1456 switch (CS.getKind()) {
1463 return false;
1464 default:
1465 return true;
1466 }
1467 }
1468 return true;
1469}
1470
1471std::optional<LengthModifier>
1473 if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
1474 if (LM.getKind() == LengthModifier::AsLongDouble ||
1475 LM.getKind() == LengthModifier::AsQuad) {
1476 LengthModifier FixedLM(LM);
1478 return FixedLM;
1479 }
1480 }
1481
1482 return std::nullopt;
1483}
1484
1486 LengthModifier &LM) {
1488 namedTypeToLengthModifierKind(Ctx, QT, Out)) {
1489 LM.setKind(Out);
1490 return true;
1491 }
1492 return false;
1493}
static clang::analyze_format_string::ArgType::MatchKind matchesSizeTPtrdiffT(ASTContext &C, QualType T, QualType E)
static analyze_format_string::ArgType::MatchKind integerTypeMatch(ASTContext &C, QualType A, QualType B, bool CheckSign)
static bool namedTypeToLengthModifierKind(ASTContext &Ctx, QualType QT, LengthModifier::Kind &K)
static bool ParseWidthModifier(const char *&I, const char *E, unsigned &BitWidth, unsigned &ModifierLength)
Defines the clang::LangOptions interface.
virtual ~FormatStringHandler()
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
const LangOptions & getLangOpts() const
Definition ASTContext.h:959
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
QualType getLeastIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
CanQualType IntTy
Pointer to a block type.
Definition TypeBase.h:3606
This class is used for builtin types like 'int'.
Definition TypeBase.h:3228
bool isInteger() const
Definition TypeBase.h:3289
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents a pointer to an Objective C object.
Definition TypeBase.h:8065
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3392
QualType getPointeeType() const
Definition TypeBase.h:3402
PredefinedSugarKind Kind
Definition TypeBase.h:8358
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
QualType getCanonicalType() const
Definition TypeBase.h:8499
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8520
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1347
Exposes information about the current target.
Definition TargetInfo.h:227
bool isStructureType() const
Definition Type.cpp:715
bool isBlockPointerType() const
Definition TypeBase.h:8704
bool isVoidType() const
Definition TypeBase.h:9050
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition Type.cpp:2266
bool canDecayToPointerType() const
Determines whether this type can decay to a pointer type.
Definition TypeBase.h:9217
bool isCharType() const
Definition Type.cpp:2193
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isSaturatedFixedPointType() const
Return true if this is a saturated fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
Definition TypeBase.h:9126
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2310
QualType getCanonicalTypeInternal() const
Definition TypeBase.h:3183
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
bool isObjCObjectPointerType() const
Definition TypeBase.h:8863
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
bool isNullPtrType() const
Definition TypeBase.h:9087
MatchKind
How well a given conversion specifier matches its argument.
@ NoMatch
The conversion specifier and the argument types are incompatible.
@ NoMatchPedantic
The conversion specifier and the argument type are disallowed by the C standard, but are in practice ...
@ Match
The conversion specifier and the argument type are compatible.
@ MatchPromotion
The conversion specifier and the argument type are compatible because of default argument promotions.
@ NoMatchSignedness
The conversion specifier and the argument type have different sign.
@ NoMatchTypeConfusion
The conversion specifier and the argument type are compatible, but still seems likely to be an error.
@ NoMatchPromotionTypeConfusion
The conversion specifier and the argument type are compatible but still seems likely to be an error.
ArgType makeVectorType(ASTContext &C, unsigned NumElts) const
MatchKind matchesArgType(ASTContext &C, const ArgType &other) const
QualType getRepresentativeType(ASTContext &C) const
std::string getRepresentativeTypeName(ASTContext &C) const
static ArgType makeIntNType(ASTContext &Ctx, const LengthModifier &LengthMod, bool Signed)
ArgType(Kind K=UnknownTy, const char *N=nullptr)
MatchKind matchesType(ASTContext &C, QualType argTy) const
std::optional< ConversionSpecifier > getStandardSpecifier() 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...
void setFieldWidth(const OptionalAmount &Amt)
bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const
bool hasValidLengthModifier(const TargetInfo &Target, const LangOptions &LO) const
std::optional< LengthModifier > getCorrectedLengthModifier() const
void setVectorNumElts(const OptionalAmount &Amt)
virtual void HandlePosition(const char *startPos, unsigned posLen)
virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, PositionContext p)
virtual void HandleZeroPosition(const char *startPos, unsigned posLen)
virtual void HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen)
Represents the length modifier in a format string in scanf/printf.
ArgType getArgType(ASTContext &Ctx) const
Defines the clang::TargetInfo interface.
bool ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &CS, const char *Start, const char *&Beg, const char *E, unsigned *argIndex)
OptionalAmount ParsePositionAmount(FormatStringHandler &H, const char *Start, const char *&Beg, const char *E, PositionContext p)
OptionalAmount ParseAmount(const char *&Beg, const char *E)
OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, unsigned &argIndex)
bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E, const LangOptions &LO, bool IsScanf=false)
Returns true if a LengthModifier was parsed and installed in the FormatSpecifier& argument,...
bool ParseArgPosition(FormatStringHandler &H, FormatSpecifier &CS, const char *Start, const char *&Beg, const char *E)
bool ParseVectorModifier(FormatStringHandler &H, FormatSpecifier &FS, const char *&Beg, const char *E, const LangOptions &LO)
bool ParseUTF8InvalidSpecifier(const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len)
Returns true if the invalid specifier in SpecifierBegin is a UTF-8 string; check that it won't go fur...
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.
Definition Decl.h:1763
IntType
===-— Target Data Type Query Methods ----------------------------—===//
Definition TargetInfo.h:147