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/Support/ConvertUTF.h"
18#include <optional>
19
26using namespace clang;
27
28// Key function to FormatStringHandler.
30
31//===----------------------------------------------------------------------===//
32// Functions for parsing format strings components in both printf and
33// scanf format strings.
34//===----------------------------------------------------------------------===//
35
37 const char *E) {
38 const char *I = Beg;
39 UpdateOnReturn<const char *> UpdateBeg(Beg, I);
40
41 unsigned accumulator = 0;
42 bool hasDigits = false;
43
44 for (; I != E; ++I) {
45 char c = *I;
46 if (c >= '0' && c <= '9') {
47 hasDigits = true;
48 accumulator = (accumulator * 10) + (c - '0');
49 continue;
50 }
51
52 if (hasDigits)
53 return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
54 false);
55
56 break;
57 }
58
59 return OptionalAmount();
60}
61
63 const char *&Beg, const char *E, unsigned &argIndex) {
64 if (*Beg == '*') {
65 ++Beg;
66 return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
67 }
68
69 return ParseAmount(Beg, E);
70}
71
73 FormatStringHandler &H, const char *Start, const char *&Beg, const char *E,
75 if (*Beg == '*') {
76 const char *I = Beg + 1;
77 const OptionalAmount &Amt = ParseAmount(I, E);
78
80 H.HandleInvalidPosition(Beg, I - Beg, p);
81 return OptionalAmount(false);
82 }
83
84 if (I == E) {
85 // No more characters left?
86 H.HandleIncompleteSpecifier(Start, E - Start);
87 return OptionalAmount(false);
88 }
89
91
92 if (*I == '$') {
93 // Handle positional arguments
94
95 // Special case: '*0$', since this is an easy mistake.
96 if (Amt.getConstantAmount() == 0) {
97 H.HandleZeroPosition(Beg, I - Beg + 1);
98 return OptionalAmount(false);
99 }
100
101 const char *Tmp = Beg;
102 Beg = ++I;
103
105 Tmp, 0, true);
106 }
107
108 H.HandleInvalidPosition(Beg, I - Beg, p);
109 return OptionalAmount(false);
110 }
111
112 return ParseAmount(Beg, E);
113}
114
116 FormatStringHandler &H, FormatSpecifier &CS, const char *Start,
117 const char *&Beg, const char *E, unsigned *argIndex) {
118 // FIXME: Support negative field widths.
119 if (argIndex) {
120 CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
121 } else {
123 H, Start, Beg, E, analyze_format_string::FieldWidthPos);
124
125 if (Amt.isInvalid())
126 return true;
127 CS.setFieldWidth(Amt);
128 }
129 return false;
130}
131
133 FormatSpecifier &FS,
134 const char *Start,
135 const char *&Beg,
136 const char *E) {
137 const char *I = Beg;
138
139 const OptionalAmount &Amt = ParseAmount(I, E);
140
141 if (I == E) {
142 // No more characters left?
143 H.HandleIncompleteSpecifier(Start, E - Start);
144 return true;
145 }
146
147 if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
148 // Warn that positional arguments are non-standard.
149 H.HandlePosition(Start, I - Start);
150
151 // Special case: '%0$', since this is an easy mistake.
152 if (Amt.getConstantAmount() == 0) {
153 H.HandleZeroPosition(Start, I - Start);
154 return true;
155 }
156
157 FS.setArgIndex(Amt.getConstantAmount() - 1);
159 // Update the caller's pointer if we decided to consume
160 // these characters.
161 Beg = I;
162 return false;
163 }
164
165 return false;
166}
167
169 FormatSpecifier &FS,
170 const char *&I,
171 const char *E,
172 const LangOptions &LO) {
173 if (!LO.OpenCL)
174 return false;
175
176 const char *Start = I;
177 if (*I == 'v') {
178 ++I;
179
180 if (I == E) {
181 H.HandleIncompleteSpecifier(Start, E - Start);
182 return true;
183 }
184
185 OptionalAmount NumElts = ParseAmount(I, E);
186 if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
187 H.HandleIncompleteSpecifier(Start, E - Start);
188 return true;
189 }
190
191 FS.setVectorNumElts(NumElts);
192 }
193
194 return false;
195}
196
198 const char *&I,
199 const char *E,
200 const LangOptions &LO,
201 bool IsScanf) {
203 const char *lmPosition = I;
204 switch (*I) {
205 default:
206 return false;
207 case 'h':
208 ++I;
209 if (I != E && *I == 'h') {
210 ++I;
211 lmKind = LengthModifier::AsChar;
212 } else if (I != E && *I == 'l' && LO.OpenCL) {
213 ++I;
215 } else {
217 }
218 break;
219 case 'l':
220 ++I;
221 if (I != E && *I == 'l') {
222 ++I;
224 } else {
225 lmKind = LengthModifier::AsLong;
226 }
227 break;
228 case 'j':
230 ++I;
231 break;
232 case 'z':
234 ++I;
235 break;
236 case 't':
238 ++I;
239 break;
240 case 'L':
242 ++I;
243 break;
244 case 'q':
245 lmKind = LengthModifier::AsQuad;
246 ++I;
247 break;
248 case 'a':
249 if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
250 // For scanf in C90, look at the next character to see if this should
251 // be parsed as the GNU extension 'a' length modifier. If not, this
252 // will be parsed as a conversion specifier.
253 ++I;
254 if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
256 break;
257 }
258 --I;
259 }
260 return false;
261 case 'm':
262 if (IsScanf) {
264 ++I;
265 break;
266 }
267 return false;
268 // printf: AsInt64, AsInt32, AsInt3264
269 // scanf: AsInt64
270 case 'I':
271 if (I + 1 != E && I + 2 != E) {
272 if (I[1] == '6' && I[2] == '4') {
273 I += 3;
275 break;
276 }
277 if (IsScanf)
278 return false;
279
280 if (I[1] == '3' && I[2] == '2') {
281 I += 3;
283 break;
284 }
285 }
286 ++I;
288 break;
289 case 'w':
290 lmKind = LengthModifier::AsWide;
291 ++I;
292 break;
293 }
294 LengthModifier lm(lmPosition, lmKind);
295 FS.setLengthModifier(lm);
296 return true;
297}
298
300 const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
301 if (SpecifierBegin + 1 >= FmtStrEnd)
302 return false;
303
304 const llvm::UTF8 *SB =
305 reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
306 const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
307 const char FirstByte = *SB;
308
309 // If the invalid specifier is a multibyte UTF-8 string, return the
310 // total length accordingly so that the conversion specifier can be
311 // properly updated to reflect a complete UTF-8 specifier.
312 unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
313 if (NumBytes == 1)
314 return false;
315 if (SB + NumBytes > SE)
316 return false;
317
318 Len = NumBytes + 1;
319 return true;
320}
321
322//===----------------------------------------------------------------------===//
323// Methods on ArgType.
324//===----------------------------------------------------------------------===//
325
328 if (!Ctx.getLangOpts().C99 && !Ctx.getLangOpts().CPlusPlus)
329 return false;
330 for (/**/; const auto *TT = QT->getAs<TypedefType>(); QT = TT->desugar()) {
331 const auto *TD = TT->getDecl();
332 const auto *DC = TT->getDecl()->getDeclContext();
333 if (DC->isTranslationUnit() || DC->isStdNamespace()) {
334 StringRef Name = TD->getIdentifier()->getName();
335 if (Name == "size_t") {
337 return true;
338 } else if (Name == "ssize_t" /*Not C99, but common in Unix.*/) {
340 return true;
341 } else if (Name == "ptrdiff_t") {
343 return true;
344 } else if (Name == "intmax_t") {
346 return true;
347 } else if (Name == "uintmax_t") {
349 return true;
350 }
351 }
352 }
353 if (const auto *PST = QT->getAs<PredefinedSugarType>()) {
354 using Kind = PredefinedSugarType::Kind;
355 switch (PST->getKind()) {
356 case Kind::SizeT:
357 case Kind::SignedSizeT:
359 return true;
360 case Kind::PtrdiffT:
362 return true;
363 }
364 llvm_unreachable("unexpected kind");
365 }
366 return false;
367}
368
369// Check whether T and E are compatible size_t/ptrdiff_t types. E must be
370// consistent with LE.
371// T is the type of the actual expression in the code to be checked, and E is
372// the expected type parsed from the format string.
376
377 if (!T->isIntegerType() || T->isBooleanType())
378 return MatchKind::NoMatch;
379
380 if (C.hasSameType(T, E))
381 return MatchKind::Match;
382
383 if (C.getCorrespondingSignedType(T.getCanonicalType()) !=
384 C.getCorrespondingSignedType(E.getCanonicalType()))
385 return MatchKind::NoMatch;
386
387 return MatchKind::NoMatchSignedness;
388}
389
392 // When using the format attribute in C++, you can receive a function or an
393 // array that will necessarily decay to a pointer when passed to the final
394 // format consumer. Apply decay before type comparison.
395 if (argTy->canDecayToPointerType())
396 argTy = C.getDecayedType(argTy);
397
398 if (Ptr) {
399 // It has to be a pointer.
400 const PointerType *PT = argTy->getAs<PointerType>();
401 if (!PT)
402 return NoMatch;
403
404 // We cannot write through a const qualified pointer.
406 return NoMatch;
407
408 argTy = PT->getPointeeType();
409 }
410
411 if (const auto *OBT = argTy->getAs<OverflowBehaviorType>())
412 argTy = OBT->getUnderlyingType();
413
414 switch (K) {
415 case InvalidTy:
416 llvm_unreachable("ArgType must be valid");
417
418 case UnknownTy:
419 return Match;
420
421 case AnyCharTy: {
422 if (const auto *ED = argTy->getAsEnumDecl()) {
423 // If the enum is incomplete we know nothing about the underlying type.
424 // Assume that it's 'int'. Do not use the underlying type for a scoped
425 // enumeration.
426 if (!ED->isComplete())
427 return NoMatch;
428 if (!ED->isScoped())
429 argTy = ED->getIntegerType();
430 }
431
432 if (const auto *BT = argTy->getAs<BuiltinType>()) {
433 // The types are perfectly matched?
434 switch (BT->getKind()) {
435 default:
436 break;
437 case BuiltinType::Char_S:
438 case BuiltinType::SChar:
439 case BuiltinType::UChar:
440 case BuiltinType::Char_U:
441 return Match;
442 case BuiltinType::Bool:
443 if (!Ptr)
444 return Match;
445 break;
446 }
447 // "Partially matched" because of promotions?
448 if (!Ptr) {
449 switch (BT->getKind()) {
450 default:
451 break;
452 case BuiltinType::Int:
453 case BuiltinType::UInt:
454 return MatchPromotion;
455 case BuiltinType::Short:
456 case BuiltinType::UShort:
457 case BuiltinType::WChar_S:
458 case BuiltinType::WChar_U:
460 }
461 }
462 }
463 return NoMatch;
464 }
465
466 case SpecificTy: {
467 if (TK != TypeKind::DontCare) {
468 return matchesSizeTPtrdiffT(C, argTy, T);
469 }
470
471 if (const auto *ED = argTy->getAsEnumDecl()) {
472 // If the enum is incomplete we know nothing about the underlying type.
473 // Assume that it's 'int'. Do not use the underlying type for a scoped
474 // enumeration as that needs an exact match.
475 if (!ED->isComplete())
476 argTy = C.IntTy;
477 else if (!ED->isScoped())
478 argTy = ED->getIntegerType();
479 }
480
481 if (argTy->isSaturatedFixedPointType())
482 argTy = C.getCorrespondingUnsaturatedType(argTy);
483
484 argTy = C.getCanonicalType(argTy).getUnqualifiedType();
485
486 if (T == argTy)
487 return Match;
488 if (const auto *BT = argTy->getAs<BuiltinType>()) {
489 // Check if the only difference between them is signed vs unsigned
490 // if true, return match signedness.
491 switch (BT->getKind()) {
492 default:
493 break;
494 case BuiltinType::Bool:
495 if (Ptr && (T == C.UnsignedCharTy || T == C.SignedCharTy))
496 return NoMatch;
497 [[fallthrough]];
498 case BuiltinType::Char_S:
499 case BuiltinType::SChar:
500 if (T == C.UnsignedShortTy || T == C.ShortTy)
502 if (T == C.UnsignedCharTy)
503 return NoMatchSignedness;
504 if (T == C.SignedCharTy)
505 return Match;
506 break;
507 case BuiltinType::Char_U:
508 case BuiltinType::UChar:
509 if (T == C.UnsignedShortTy || T == C.ShortTy)
511 if (T == C.UnsignedCharTy)
512 return Match;
513 if (T == C.SignedCharTy)
514 return NoMatchSignedness;
515 break;
516 case BuiltinType::Short:
517 if (T == C.UnsignedShortTy)
518 return NoMatchSignedness;
519 break;
520 case BuiltinType::UShort:
521 if (T == C.ShortTy)
522 return NoMatchSignedness;
523 break;
524 case BuiltinType::Int:
525 if (T == C.UnsignedIntTy)
526 return NoMatchSignedness;
527 break;
528 case BuiltinType::UInt:
529 if (T == C.IntTy)
530 return NoMatchSignedness;
531 break;
532 case BuiltinType::Long:
533 if (T == C.UnsignedLongTy)
534 return NoMatchSignedness;
535 break;
536 case BuiltinType::ULong:
537 if (T == C.LongTy)
538 return NoMatchSignedness;
539 break;
540 case BuiltinType::LongLong:
541 if (T == C.UnsignedLongLongTy)
542 return NoMatchSignedness;
543 break;
544 case BuiltinType::ULongLong:
545 if (T == C.LongLongTy)
546 return NoMatchSignedness;
547 break;
548 }
549 // "Partially matched" because of promotions?
550 if (!Ptr) {
551 switch (BT->getKind()) {
552 default:
553 break;
554 case BuiltinType::Bool:
555 if (T == C.IntTy || T == C.UnsignedIntTy)
556 return MatchPromotion;
557 break;
558 case BuiltinType::Int:
559 case BuiltinType::UInt:
560 if (T == C.SignedCharTy || T == C.UnsignedCharTy || T == C.ShortTy ||
561 T == C.UnsignedShortTy || T == C.WCharTy || T == C.WideCharTy)
562 return MatchPromotion;
563 break;
564 case BuiltinType::Char_U:
565 if (T == C.UnsignedIntTy)
566 return MatchPromotion;
567 if (T == C.UnsignedShortTy)
569 break;
570 case BuiltinType::Char_S:
571 if (T == C.IntTy)
572 return MatchPromotion;
573 if (T == C.ShortTy)
575 break;
576 case BuiltinType::Half:
577 case BuiltinType::Float:
578 if (T == C.DoubleTy)
579 return MatchPromotion;
580 break;
581 case BuiltinType::Short:
582 case BuiltinType::UShort:
583 if (T == C.SignedCharTy || T == C.UnsignedCharTy)
585 break;
586 case BuiltinType::WChar_U:
587 case BuiltinType::WChar_S:
588 if (T != C.WCharTy && T != C.WideCharTy)
590 }
591 }
592 }
593 return NoMatch;
594 }
595
596 case CStrTy:
597 if (const auto *PT = argTy->getAs<PointerType>();
598 PT && PT->getPointeeType()->isCharType())
599 return Match;
600 return NoMatch;
601
602 case WCStrTy:
603 if (const auto *PT = argTy->getAs<PointerType>();
604 PT &&
605 C.hasSameUnqualifiedType(PT->getPointeeType(), C.getWideCharType()))
606 return Match;
607 return NoMatch;
608
609 case WIntTy: {
610 QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
611
612 if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)
613 return Match;
614
615 QualType PromoArg = C.isPromotableIntegerType(argTy)
616 ? C.getPromotedIntegerType(argTy)
617 : argTy;
618 PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
619
620 // If the promoted argument is the corresponding signed type of the
621 // wint_t type, then it should match.
622 if (PromoArg->hasSignedIntegerRepresentation() &&
623 C.getCorrespondingUnsignedType(PromoArg) == WInt)
624 return Match;
625
626 return WInt == PromoArg ? Match : NoMatch;
627 }
628
629 case CPointerTy:
630 if (const auto *PT = argTy->getAs<PointerType>()) {
631 QualType PointeeTy = PT->getPointeeType();
632 if (PointeeTy->isVoidType() || (!Ptr && PointeeTy->isCharType()))
633 return Match;
634 return NoMatchPedantic;
635 }
636
637 // nullptr_t* is not a double pointer, so reject when something like
638 // void** is expected.
639 // In C++, nullptr is promoted to void*. In C23, va_arg(ap, void*) is not
640 // undefined when the next argument is of type nullptr_t.
641 if (!Ptr && argTy->isNullPtrType())
642 return C.getLangOpts().CPlusPlus ? MatchPromotion : Match;
643
644 if (argTy->isObjCObjectPointerType() || argTy->isBlockPointerType())
645 return NoMatchPedantic;
646
647 return NoMatch;
648
649 case ObjCPointerTy: {
650 if (argTy->getAs<ObjCObjectPointerType>() ||
651 argTy->getAs<BlockPointerType>())
652 return Match;
653
654 // Handle implicit toll-free bridging.
655 if (const PointerType *PT = argTy->getAs<PointerType>()) {
656 // Things such as CFTypeRef are really just opaque pointers
657 // to C structs representing CF types that can often be bridged
658 // to Objective-C objects. Since the compiler doesn't know which
659 // structs can be toll-free bridged, we just accept them all.
660 QualType pointee = PT->getPointeeType();
661 if (pointee->isStructureType() || pointee->isVoidType())
662 return Match;
663 }
664 return NoMatch;
665 }
666 }
667
668 llvm_unreachable("Invalid ArgType Kind!");
669}
670
674
675 uint64_t IntSize = C.getTypeSize(C.IntTy);
676 uint64_t ASize = C.getTypeSize(A);
677 uint64_t BSize = C.getTypeSize(B);
678 if (std::max(ASize, IntSize) != std::max(BSize, IntSize))
679 return MK::NoMatch;
680 if (CheckSign && A->isSignedIntegerType() != B->isSignedIntegerType())
681 return MK::NoMatchSignedness;
682 if (ASize != BSize)
683 return MK::MatchPromotion;
684 return MK::Match;
685}
686
690
691 // Per matchesType.
692 if (K == AK::InvalidTy || Other.K == AK::InvalidTy)
693 return NoMatch;
694 if (K == AK::UnknownTy || Other.K == AK::UnknownTy)
695 return Match;
696
697 // Handle whether either (or both, or neither) sides has Ptr set,
698 // in addition to whether either (or both, or neither) sides is a SpecificTy
699 // that is a pointer.
700 ArgType Left = *this;
701 bool LeftWasPointer = false;
702 ArgType Right = Other;
703 bool RightWasPointer = false;
704 if (Left.Ptr) {
705 Left.Ptr = false;
706 LeftWasPointer = true;
707 } else if (Left.K == AK::SpecificTy && Left.T->isPointerType()) {
708 Left.T = Left.T->getPointeeType();
709 LeftWasPointer = true;
710 }
711 if (Right.Ptr) {
712 Right.Ptr = false;
713 RightWasPointer = true;
714 } else if (Right.K == AK::SpecificTy && Right.T->isPointerType()) {
715 Right.T = Right.T->getPointeeType();
716 RightWasPointer = true;
717 }
718
719 if (LeftWasPointer != RightWasPointer)
720 return NoMatch;
721
722 // Ensure that if at least one side is a SpecificTy, then Left is a
723 // SpecificTy.
724 if (Right.K == AK::SpecificTy)
725 std::swap(Left, Right);
726
727 if (Left.K == AK::SpecificTy) {
728 if (Right.K == AK::SpecificTy) {
729 if (Left.TK != TypeKind::DontCare) {
730 return matchesSizeTPtrdiffT(C, Right.T, Left.T);
731 } else if (Right.TK != TypeKind::DontCare) {
732 return matchesSizeTPtrdiffT(C, Left.T, Right.T);
733 }
734
735 auto Canon1 = C.getCanonicalType(Left.T);
736 auto Canon2 = C.getCanonicalType(Right.T);
737 if (Canon1 == Canon2)
738 return Match;
739
740 auto *BT1 = QualType(Canon1)->getAs<BuiltinType>();
741 auto *BT2 = QualType(Canon2)->getAs<BuiltinType>();
742 if (BT1 == nullptr || BT2 == nullptr)
743 return NoMatch;
744 if (BT1 == BT2)
745 return Match;
746
747 if (!LeftWasPointer && BT1->isInteger() && BT2->isInteger())
748 return integerTypeMatch(C, Canon1, Canon2, true);
749 return NoMatch;
750 } else if (Right.K == AK::AnyCharTy) {
751 if (!LeftWasPointer && Left.T->isIntegerType())
752 return integerTypeMatch(C, Left.T, C.CharTy, false);
753 return NoMatch;
754 } else if (Right.K == AK::WIntTy) {
755 if (!LeftWasPointer && Left.T->isIntegerType())
756 return integerTypeMatch(C, Left.T, C.WIntTy, true);
757 return NoMatch;
758 }
759 // It's hypothetically possible to create an AK::SpecificTy ArgType
760 // that matches another kind of ArgType, but in practice Clang doesn't
761 // do that, so ignore that case.
762 return NoMatch;
763 }
764
765 return Left.K == Right.K ? Match : NoMatch;
766}
767
768ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
769 // Check for valid vector element types.
770 if (T.isNull())
771 return ArgType::Invalid();
772
773 QualType Vec = C.getExtVectorType(T, NumElts);
774 return ArgType(Vec, Name);
775}
776
778 QualType Res;
779 switch (K) {
780 case InvalidTy:
781 llvm_unreachable("No representative type for Invalid ArgType");
782 case UnknownTy:
783 llvm_unreachable("No representative type for Unknown ArgType");
784 case AnyCharTy:
785 Res = C.CharTy;
786 break;
787 case SpecificTy:
788 if (TK == TypeKind::PtrdiffT || TK == TypeKind::SizeT)
789 // Using Name as name, so no need to show the uglified name.
790 Res = T->getCanonicalTypeInternal();
791 else
792 Res = T;
793 break;
794 case CStrTy:
795 Res = C.getPointerType(C.CharTy);
796 break;
797 case WCStrTy:
798 Res = C.getPointerType(C.getWideCharType());
799 break;
800 case ObjCPointerTy:
801 Res = C.ObjCBuiltinIdTy;
802 break;
803 case CPointerTy:
804 Res = C.VoidPtrTy;
805 break;
806 case WIntTy: {
807 Res = C.getWIntType();
808 break;
809 }
810 }
811
812 if (Ptr)
813 Res = C.getPointerType(Res);
814 return Res;
815}
816
818 std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy());
819 std::string Alias;
820 if (Name) {
821 // Use a specific name for this type, e.g. "size_t".
822 Alias = Name;
823 if (Ptr) {
824 // If ArgType is actually a pointer to T, append an asterisk.
825 Alias += (Alias[Alias.size() - 1] == '*') ? "*" : " *";
826 }
827 // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
828 if (S == Alias)
829 Alias.clear();
830 }
831
832 if (!Alias.empty())
833 return std::string("'") + Alias + "' (aka '" + S + "')";
834 return std::string("'") + S + "'";
835}
836
837//===----------------------------------------------------------------------===//
838// Methods on OptionalAmount.
839//===----------------------------------------------------------------------===//
840
845
846//===----------------------------------------------------------------------===//
847// Methods on LengthModifier.
848//===----------------------------------------------------------------------===//
849
851 switch (kind) {
852 case AsChar:
853 return "hh";
854 case AsShort:
855 return "h";
856 case AsShortLong:
857 return "hl";
858 case AsLong: // or AsWideChar
859 return "l";
860 case AsLongLong:
861 return "ll";
862 case AsQuad:
863 return "q";
864 case AsIntMax:
865 return "j";
866 case AsSizeT:
867 return "z";
868 case AsPtrDiff:
869 return "t";
870 case AsInt32:
871 return "I32";
872 case AsInt3264:
873 return "I";
874 case AsInt64:
875 return "I64";
876 case AsLongDouble:
877 return "L";
878 case AsAllocate:
879 return "a";
880 case AsMAllocate:
881 return "m";
882 case AsWide:
883 return "w";
884 case None:
885 return "";
886 }
887 return nullptr;
888}
889
890//===----------------------------------------------------------------------===//
891// Methods on ConversionSpecifier.
892//===----------------------------------------------------------------------===//
893
894const char *ConversionSpecifier::toString() const {
895 switch (kind) {
896 case bArg:
897 return "b";
898 case BArg:
899 return "B";
900 case dArg:
901 return "d";
902 case DArg:
903 return "D";
904 case iArg:
905 return "i";
906 case oArg:
907 return "o";
908 case OArg:
909 return "O";
910 case uArg:
911 return "u";
912 case UArg:
913 return "U";
914 case xArg:
915 return "x";
916 case XArg:
917 return "X";
918 case fArg:
919 return "f";
920 case FArg:
921 return "F";
922 case eArg:
923 return "e";
924 case EArg:
925 return "E";
926 case gArg:
927 return "g";
928 case GArg:
929 return "G";
930 case aArg:
931 return "a";
932 case AArg:
933 return "A";
934 case cArg:
935 return "c";
936 case sArg:
937 return "s";
938 case pArg:
939 return "p";
940 case PArg:
941 return "P";
942 case nArg:
943 return "n";
944 case PercentArg:
945 return "%";
946 case ScanListArg:
947 return "[";
948 case InvalidSpecifier:
949 return nullptr;
950
951 // POSIX unicode extensions.
952 case CArg:
953 return "C";
954 case SArg:
955 return "S";
956
957 // Objective-C specific specifiers.
958 case ObjCObjArg:
959 return "@";
960
961 // FreeBSD kernel specific specifiers.
962 case FreeBSDbArg:
963 return "b";
964 case FreeBSDDArg:
965 return "D";
966 case FreeBSDrArg:
967 return "r";
968 case FreeBSDyArg:
969 return "y";
970
971 // GlibC specific specifiers.
972 case PrintErrno:
973 return "m";
974
975 // MS specific specifiers.
976 case ZArg:
977 return "Z";
978
979 // ISO/IEC TR 18037 (fixed-point) specific specifiers.
980 case rArg:
981 return "r";
982 case RArg:
983 return "R";
984 case kArg:
985 return "k";
986 case KArg:
987 return "K";
988 }
989 return nullptr;
990}
991
992std::optional<ConversionSpecifier>
995
996 switch (getKind()) {
997 default:
998 return std::nullopt;
999 case DArg:
1000 NewKind = dArg;
1001 break;
1002 case UArg:
1003 NewKind = uArg;
1004 break;
1005 case OArg:
1006 NewKind = oArg;
1007 break;
1008 }
1009
1010 ConversionSpecifier FixedCS(*this);
1011 FixedCS.setKind(NewKind);
1012 return FixedCS;
1013}
1014
1015//===----------------------------------------------------------------------===//
1016// Methods on OptionalAmount.
1017//===----------------------------------------------------------------------===//
1018
1019void OptionalAmount::toString(raw_ostream &os) const {
1020 switch (hs) {
1021 case Invalid:
1022 case NotSpecified:
1023 return;
1024 case Arg:
1025 if (UsesDotPrefix)
1026 os << ".";
1027 if (usesPositionalArg())
1028 os << "*" << getPositionalArgIndex() << "$";
1029 else
1030 os << "*";
1031 break;
1032 case Constant:
1033 if (UsesDotPrefix)
1034 os << ".";
1035 os << amt;
1036 break;
1037 }
1038}
1039
1041 const LangOptions &LO) const {
1042 switch (LM.getKind()) {
1044 return true;
1045
1046 // Handle most integer flags
1048 // Length modifier only applies to FP vectors.
1049 if (LO.OpenCL && CS.isDoubleArg())
1050 return !VectorNumElts.isInvalid();
1051
1052 if (CS.isFixedPointArg())
1053 return true;
1054
1055 if (Target.getTriple().isOSMSVCRT()) {
1056 switch (CS.getKind()) {
1062 return true;
1063 default:
1064 break;
1065 }
1066 }
1067 [[fallthrough]];
1074 switch (CS.getKind()) {
1087 return true;
1090 return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
1091 default:
1092 return false;
1093 }
1094
1096 return LO.OpenCL && !VectorNumElts.isInvalid();
1097
1098 // Handle 'l' flag
1099 case LengthModifier::AsLong: // or AsWideChar
1100 if (CS.isDoubleArg()) {
1101 // Invalid for OpenCL FP scalars.
1102 if (LO.OpenCL && VectorNumElts.isInvalid())
1103 return false;
1104 return true;
1105 }
1106
1107 if (CS.isFixedPointArg())
1108 return true;
1109
1110 switch (CS.getKind()) {
1127 return true;
1130 return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
1131 default:
1132 return false;
1133 }
1134
1136 switch (CS.getKind()) {
1145 return true;
1146 // GNU libc extension.
1153 return !Target.getTriple().isOSDarwin() &&
1154 !Target.getTriple().isOSWindows();
1155 default:
1156 return false;
1157 }
1158
1160 switch (CS.getKind()) {
1164 return true;
1165 default:
1166 return false;
1167 }
1168
1170 switch (CS.getKind()) {
1176 return true;
1177 default:
1178 return false;
1179 }
1183 switch (CS.getKind()) {
1190 return Target.getTriple().isOSMSVCRT();
1191 default:
1192 return false;
1193 }
1195 switch (CS.getKind()) {
1201 return Target.getTriple().isOSMSVCRT();
1202 default:
1203 return false;
1204 }
1205 }
1206 llvm_unreachable("Invalid LengthModifier Kind!");
1207}
1208
1210 switch (LM.getKind()) {
1220 return true;
1228 case LengthModifier::AsShortLong: // ???
1229 return false;
1230 }
1231 llvm_unreachable("Invalid LengthModifier Kind!");
1232}
1233
1235 const LangOptions &LangOpt) const {
1236 switch (CS.getKind()) {
1261 return true;
1264 return LangOpt.ObjC;
1275 return false;
1280 return LangOpt.FixedPoint;
1281 }
1282 llvm_unreachable("Invalid ConversionSpecifier Kind!");
1283}
1284
1286 if (LM.getKind() == LengthModifier::AsLongDouble) {
1287 switch (CS.getKind()) {
1294 return false;
1295 default:
1296 return true;
1297 }
1298 }
1299 return true;
1300}
1301
1302std::optional<LengthModifier>
1304 if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
1305 if (LM.getKind() == LengthModifier::AsLongDouble ||
1306 LM.getKind() == LengthModifier::AsQuad) {
1307 LengthModifier FixedLM(LM);
1309 return FixedLM;
1310 }
1311 }
1312
1313 return std::nullopt;
1314}
1315
1317 LengthModifier &LM) {
1319 namedTypeToLengthModifierKind(Ctx, QT, Out)) {
1320 LM.setKind(Out);
1321 return true;
1322 }
1323 return false;
1324}
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)
Defines the clang::LangOptions interface.
__device__ __2f16 float c
virtual ~FormatStringHandler()
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:227
const LangOptions & getLangOpts() const
Definition ASTContext.h:959
CanQualType IntTy
Pointer to a block type.
Definition TypeBase.h:3597
This class is used for builtin types like 'int'.
Definition TypeBase.h:3219
bool isInteger() const
Definition TypeBase.h:3280
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:8054
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3383
QualType getPointeeType() const
Definition TypeBase.h:3393
PredefinedSugarKind Kind
Definition TypeBase.h:8347
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType getCanonicalType() const
Definition TypeBase.h:8488
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8509
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1343
Exposes information about the current target.
Definition TargetInfo.h:227
bool isStructureType() const
Definition Type.cpp:715
bool isBlockPointerType() const
Definition TypeBase.h:8693
bool isVoidType() const
Definition TypeBase.h:9039
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:9206
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:9115
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:3174
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
bool isObjCObjectPointerType() const
Definition TypeBase.h:8852
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9266
bool isNullPtrType() const
Definition TypeBase.h:9076
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
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