clang  19.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"
16 #include "clang/Basic/TargetInfo.h"
17 #include "llvm/Support/ConvertUTF.h"
18 #include <optional>
19 
26 using namespace clang;
27 
28 // Key function to FormatStringHandler.
29 FormatStringHandler::~FormatStringHandler() {}
30 
31 //===----------------------------------------------------------------------===//
32 // Functions for parsing format strings components in both printf and
33 // scanf format strings.
34 //===----------------------------------------------------------------------===//
35 
37 clang::analyze_format_string::ParseAmount(const char *&Beg, 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 
64  const char *E,
65  unsigned &argIndex) {
66  if (*Beg == '*') {
67  ++Beg;
68  return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
69  }
70 
71  return ParseAmount(Beg, E);
72 }
73 
76  const char *Start,
77  const char *&Beg,
78  const char *E,
79  PositionContext p) {
80  if (*Beg == '*') {
81  const char *I = Beg + 1;
82  const OptionalAmount &Amt = ParseAmount(I, E);
83 
84  if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
85  H.HandleInvalidPosition(Beg, I - Beg, p);
86  return OptionalAmount(false);
87  }
88 
89  if (I == E) {
90  // No more characters left?
91  H.HandleIncompleteSpecifier(Start, E - Start);
92  return OptionalAmount(false);
93  }
94 
95  assert(Amt.getHowSpecified() == OptionalAmount::Constant);
96 
97  if (*I == '$') {
98  // Handle positional arguments
99 
100  // Special case: '*0$', since this is an easy mistake.
101  if (Amt.getConstantAmount() == 0) {
102  H.HandleZeroPosition(Beg, I - Beg + 1);
103  return OptionalAmount(false);
104  }
105 
106  const char *Tmp = Beg;
107  Beg = ++I;
108 
109  return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
110  Tmp, 0, true);
111  }
112 
113  H.HandleInvalidPosition(Beg, I - Beg, p);
114  return OptionalAmount(false);
115  }
116 
117  return ParseAmount(Beg, E);
118 }
119 
120 
121 bool
123  FormatSpecifier &CS,
124  const char *Start,
125  const char *&Beg, const char *E,
126  unsigned *argIndex) {
127  // FIXME: Support negative field widths.
128  if (argIndex) {
129  CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
130  }
131  else {
132  const OptionalAmount Amt =
133  ParsePositionAmount(H, Start, Beg, E,
135 
136  if (Amt.isInvalid())
137  return true;
138  CS.setFieldWidth(Amt);
139  }
140  return false;
141 }
142 
143 bool
145  FormatSpecifier &FS,
146  const char *Start,
147  const char *&Beg,
148  const char *E) {
149  const char *I = Beg;
150 
151  const OptionalAmount &Amt = ParseAmount(I, E);
152 
153  if (I == E) {
154  // No more characters left?
155  H.HandleIncompleteSpecifier(Start, E - Start);
156  return true;
157  }
158 
159  if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
160  // Warn that positional arguments are non-standard.
161  H.HandlePosition(Start, I - Start);
162 
163  // Special case: '%0$', since this is an easy mistake.
164  if (Amt.getConstantAmount() == 0) {
165  H.HandleZeroPosition(Start, I - Start);
166  return true;
167  }
168 
169  FS.setArgIndex(Amt.getConstantAmount() - 1);
170  FS.setUsesPositionalArg();
171  // Update the caller's pointer if we decided to consume
172  // these characters.
173  Beg = I;
174  return false;
175  }
176 
177  return false;
178 }
179 
180 bool
182  FormatSpecifier &FS,
183  const char *&I,
184  const char *E,
185  const LangOptions &LO) {
186  if (!LO.OpenCL)
187  return false;
188 
189  const char *Start = I;
190  if (*I == 'v') {
191  ++I;
192 
193  if (I == E) {
194  H.HandleIncompleteSpecifier(Start, E - Start);
195  return true;
196  }
197 
198  OptionalAmount NumElts = ParseAmount(I, E);
199  if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
200  H.HandleIncompleteSpecifier(Start, E - Start);
201  return true;
202  }
203 
204  FS.setVectorNumElts(NumElts);
205  }
206 
207  return false;
208 }
209 
210 bool
212  const char *&I,
213  const char *E,
214  const LangOptions &LO,
215  bool IsScanf) {
217  const char *lmPosition = I;
218  switch (*I) {
219  default:
220  return false;
221  case 'h':
222  ++I;
223  if (I != E && *I == 'h') {
224  ++I;
225  lmKind = LengthModifier::AsChar;
226  } else if (I != E && *I == 'l' && LO.OpenCL) {
227  ++I;
228  lmKind = LengthModifier::AsShortLong;
229  } else {
230  lmKind = LengthModifier::AsShort;
231  }
232  break;
233  case 'l':
234  ++I;
235  if (I != E && *I == 'l') {
236  ++I;
237  lmKind = LengthModifier::AsLongLong;
238  } else {
239  lmKind = LengthModifier::AsLong;
240  }
241  break;
242  case 'j': lmKind = LengthModifier::AsIntMax; ++I; break;
243  case 'z': lmKind = LengthModifier::AsSizeT; ++I; break;
244  case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break;
245  case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
246  case 'q': lmKind = LengthModifier::AsQuad; ++I; break;
247  case 'a':
248  if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
249  // For scanf in C90, look at the next character to see if this should
250  // be parsed as the GNU extension 'a' length modifier. If not, this
251  // will be parsed as a conversion specifier.
252  ++I;
253  if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
254  lmKind = LengthModifier::AsAllocate;
255  break;
256  }
257  --I;
258  }
259  return false;
260  case 'm':
261  if (IsScanf) {
262  lmKind = LengthModifier::AsMAllocate;
263  ++I;
264  break;
265  }
266  return false;
267  // printf: AsInt64, AsInt32, AsInt3264
268  // scanf: AsInt64
269  case 'I':
270  if (I + 1 != E && I + 2 != E) {
271  if (I[1] == '6' && I[2] == '4') {
272  I += 3;
273  lmKind = LengthModifier::AsInt64;
274  break;
275  }
276  if (IsScanf)
277  return false;
278 
279  if (I[1] == '3' && I[2] == '2') {
280  I += 3;
281  lmKind = LengthModifier::AsInt32;
282  break;
283  }
284  }
285  ++I;
286  lmKind = LengthModifier::AsInt3264;
287  break;
288  case 'w':
289  lmKind = LengthModifier::AsWide; ++I; break;
290  }
291  LengthModifier lm(lmPosition, lmKind);
292  FS.setLengthModifier(lm);
293  return true;
294 }
295 
297  const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
298  if (SpecifierBegin + 1 >= FmtStrEnd)
299  return false;
300 
301  const llvm::UTF8 *SB =
302  reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
303  const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
304  const char FirstByte = *SB;
305 
306  // If the invalid specifier is a multibyte UTF-8 string, return the
307  // total length accordingly so that the conversion specifier can be
308  // properly updated to reflect a complete UTF-8 specifier.
309  unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
310  if (NumBytes == 1)
311  return false;
312  if (SB + NumBytes > SE)
313  return false;
314 
315  Len = NumBytes + 1;
316  return true;
317 }
318 
319 //===----------------------------------------------------------------------===//
320 // Methods on ArgType.
321 //===----------------------------------------------------------------------===//
322 
324 ArgType::matchesType(ASTContext &C, QualType argTy) const {
325  // When using the format attribute in C++, you can receive a function or an
326  // array that will necessarily decay to a pointer when passed to the final
327  // format consumer. Apply decay before type comparison.
328  if (argTy->canDecayToPointerType())
329  argTy = C.getDecayedType(argTy);
330 
331  if (Ptr) {
332  // It has to be a pointer.
333  const PointerType *PT = argTy->getAs<PointerType>();
334  if (!PT)
335  return NoMatch;
336 
337  // We cannot write through a const qualified pointer.
338  if (PT->getPointeeType().isConstQualified())
339  return NoMatch;
340 
341  argTy = PT->getPointeeType();
342  }
343 
344  switch (K) {
345  case InvalidTy:
346  llvm_unreachable("ArgType must be valid");
347 
348  case UnknownTy:
349  return Match;
350 
351  case AnyCharTy: {
352  if (const auto *ETy = argTy->getAs<EnumType>()) {
353  // If the enum is incomplete we know nothing about the underlying type.
354  // Assume that it's 'int'. Do not use the underlying type for a scoped
355  // enumeration.
356  if (!ETy->getDecl()->isComplete())
357  return NoMatch;
358  if (ETy->isUnscopedEnumerationType())
359  argTy = ETy->getDecl()->getIntegerType();
360  }
361 
362  if (const auto *BT = argTy->getAs<BuiltinType>()) {
363  // The types are perfectly matched?
364  switch (BT->getKind()) {
365  default:
366  break;
367  case BuiltinType::Char_S:
368  case BuiltinType::SChar:
369  case BuiltinType::UChar:
370  case BuiltinType::Char_U:
371  return Match;
372  case BuiltinType::Bool:
373  if (!Ptr)
374  return Match;
375  break;
376  }
377  // "Partially matched" because of promotions?
378  if (!Ptr) {
379  switch (BT->getKind()) {
380  default:
381  break;
382  case BuiltinType::Int:
383  case BuiltinType::UInt:
384  return MatchPromotion;
385  case BuiltinType::Short:
386  case BuiltinType::UShort:
387  case BuiltinType::WChar_S:
388  case BuiltinType::WChar_U:
389  return NoMatchPromotionTypeConfusion;
390  }
391  }
392  }
393  return NoMatch;
394  }
395 
396  case SpecificTy: {
397  if (const EnumType *ETy = argTy->getAs<EnumType>()) {
398  // If the enum is incomplete we know nothing about the underlying type.
399  // Assume that it's 'int'. Do not use the underlying type for a scoped
400  // enumeration as that needs an exact match.
401  if (!ETy->getDecl()->isComplete())
402  argTy = C.IntTy;
403  else if (ETy->isUnscopedEnumerationType())
404  argTy = ETy->getDecl()->getIntegerType();
405  }
406 
407  if (argTy->isSaturatedFixedPointType())
408  argTy = C.getCorrespondingUnsaturatedType(argTy);
409 
410  argTy = C.getCanonicalType(argTy).getUnqualifiedType();
411 
412  if (T == argTy)
413  return Match;
414  if (const auto *BT = argTy->getAs<BuiltinType>()) {
415  // Check if the only difference between them is signed vs unsigned
416  // if true, return match signedness.
417  switch (BT->getKind()) {
418  default:
419  break;
420  case BuiltinType::Bool:
421  if (Ptr && (T == C.UnsignedCharTy || T == C.SignedCharTy))
422  return NoMatch;
423  [[fallthrough]];
424  case BuiltinType::Char_S:
425  case BuiltinType::SChar:
426  if (T == C.UnsignedShortTy || T == C.ShortTy)
427  return NoMatchTypeConfusion;
428  if (T == C.UnsignedCharTy)
429  return NoMatchSignedness;
430  if (T == C.SignedCharTy)
431  return Match;
432  break;
433  case BuiltinType::Char_U:
434  case BuiltinType::UChar:
435  if (T == C.UnsignedShortTy || T == C.ShortTy)
436  return NoMatchTypeConfusion;
437  if (T == C.UnsignedCharTy)
438  return Match;
439  if (T == C.SignedCharTy)
440  return NoMatchSignedness;
441  break;
442  case BuiltinType::Short:
443  if (T == C.UnsignedShortTy)
444  return NoMatchSignedness;
445  break;
446  case BuiltinType::UShort:
447  if (T == C.ShortTy)
448  return NoMatchSignedness;
449  break;
450  case BuiltinType::Int:
451  if (T == C.UnsignedIntTy)
452  return NoMatchSignedness;
453  break;
454  case BuiltinType::UInt:
455  if (T == C.IntTy)
456  return NoMatchSignedness;
457  break;
458  case BuiltinType::Long:
459  if (T == C.UnsignedLongTy)
460  return NoMatchSignedness;
461  break;
462  case BuiltinType::ULong:
463  if (T == C.LongTy)
464  return NoMatchSignedness;
465  break;
466  case BuiltinType::LongLong:
467  if (T == C.UnsignedLongLongTy)
468  return NoMatchSignedness;
469  break;
470  case BuiltinType::ULongLong:
471  if (T == C.LongLongTy)
472  return NoMatchSignedness;
473  break;
474  }
475  // "Partially matched" because of promotions?
476  if (!Ptr) {
477  switch (BT->getKind()) {
478  default:
479  break;
480  case BuiltinType::Bool:
481  if (T == C.IntTy || T == C.UnsignedIntTy)
482  return MatchPromotion;
483  break;
484  case BuiltinType::Int:
485  case BuiltinType::UInt:
486  if (T == C.SignedCharTy || T == C.UnsignedCharTy ||
487  T == C.ShortTy || T == C.UnsignedShortTy || T == C.WCharTy ||
488  T == C.WideCharTy)
489  return MatchPromotion;
490  break;
491  case BuiltinType::Char_U:
492  if (T == C.UnsignedIntTy)
493  return MatchPromotion;
494  if (T == C.UnsignedShortTy)
495  return NoMatchPromotionTypeConfusion;
496  break;
497  case BuiltinType::Char_S:
498  if (T == C.IntTy)
499  return MatchPromotion;
500  if (T == C.ShortTy)
501  return NoMatchPromotionTypeConfusion;
502  break;
503  case BuiltinType::Half:
504  case BuiltinType::Float:
505  if (T == C.DoubleTy)
506  return MatchPromotion;
507  break;
508  case BuiltinType::Short:
509  case BuiltinType::UShort:
510  if (T == C.SignedCharTy || T == C.UnsignedCharTy)
511  return NoMatchPromotionTypeConfusion;
512  break;
513  case BuiltinType::WChar_U:
514  case BuiltinType::WChar_S:
515  if (T != C.WCharTy && T != C.WideCharTy)
516  return NoMatchPromotionTypeConfusion;
517  }
518  }
519  }
520  return NoMatch;
521  }
522 
523  case CStrTy: {
524  const PointerType *PT = argTy->getAs<PointerType>();
525  if (!PT)
526  return NoMatch;
527  QualType pointeeTy = PT->getPointeeType();
528  if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
529  switch (BT->getKind()) {
530  case BuiltinType::Char_U:
531  case BuiltinType::UChar:
532  case BuiltinType::Char_S:
533  case BuiltinType::SChar:
534  return Match;
535  default:
536  break;
537  }
538 
539  return NoMatch;
540  }
541 
542  case WCStrTy: {
543  const PointerType *PT = argTy->getAs<PointerType>();
544  if (!PT)
545  return NoMatch;
546  QualType pointeeTy =
547  C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
548  return pointeeTy == C.getWideCharType() ? Match : NoMatch;
549  }
550 
551  case WIntTy: {
552  QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
553 
554  if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)
555  return Match;
556 
557  QualType PromoArg = C.isPromotableIntegerType(argTy)
558  ? C.getPromotedIntegerType(argTy)
559  : argTy;
560  PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
561 
562  // If the promoted argument is the corresponding signed type of the
563  // wint_t type, then it should match.
564  if (PromoArg->hasSignedIntegerRepresentation() &&
565  C.getCorrespondingUnsignedType(PromoArg) == WInt)
566  return Match;
567 
568  return WInt == PromoArg ? Match : NoMatch;
569  }
570 
571  case CPointerTy:
572  if (argTy->isVoidPointerType()) {
573  return Match;
574  } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
575  argTy->isBlockPointerType() || argTy->isNullPtrType()) {
576  return NoMatchPedantic;
577  } else {
578  return NoMatch;
579  }
580 
581  case ObjCPointerTy: {
582  if (argTy->getAs<ObjCObjectPointerType>() ||
583  argTy->getAs<BlockPointerType>())
584  return Match;
585 
586  // Handle implicit toll-free bridging.
587  if (const PointerType *PT = argTy->getAs<PointerType>()) {
588  // Things such as CFTypeRef are really just opaque pointers
589  // to C structs representing CF types that can often be bridged
590  // to Objective-C objects. Since the compiler doesn't know which
591  // structs can be toll-free bridged, we just accept them all.
592  QualType pointee = PT->getPointeeType();
593  if (pointee->getAsStructureType() || pointee->isVoidType())
594  return Match;
595  }
596  return NoMatch;
597  }
598  }
599 
600  llvm_unreachable("Invalid ArgType Kind!");
601 }
602 
603 ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
604  // Check for valid vector element types.
605  if (T.isNull())
606  return ArgType::Invalid();
607 
608  QualType Vec = C.getExtVectorType(T, NumElts);
609  return ArgType(Vec, Name);
610 }
611 
612 QualType ArgType::getRepresentativeType(ASTContext &C) const {
613  QualType Res;
614  switch (K) {
615  case InvalidTy:
616  llvm_unreachable("No representative type for Invalid ArgType");
617  case UnknownTy:
618  llvm_unreachable("No representative type for Unknown ArgType");
619  case AnyCharTy:
620  Res = C.CharTy;
621  break;
622  case SpecificTy:
623  Res = T;
624  break;
625  case CStrTy:
626  Res = C.getPointerType(C.CharTy);
627  break;
628  case WCStrTy:
629  Res = C.getPointerType(C.getWideCharType());
630  break;
631  case ObjCPointerTy:
632  Res = C.ObjCBuiltinIdTy;
633  break;
634  case CPointerTy:
635  Res = C.VoidPtrTy;
636  break;
637  case WIntTy: {
638  Res = C.getWIntType();
639  break;
640  }
641  }
642 
643  if (Ptr)
644  Res = C.getPointerType(Res);
645  return Res;
646 }
647 
648 std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
649  std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy());
650 
651  std::string Alias;
652  if (Name) {
653  // Use a specific name for this type, e.g. "size_t".
654  Alias = Name;
655  if (Ptr) {
656  // If ArgType is actually a pointer to T, append an asterisk.
657  Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";
658  }
659  // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
660  if (S == Alias)
661  Alias.clear();
662  }
663 
664  if (!Alias.empty())
665  return std::string("'") + Alias + "' (aka '" + S + "')";
666  return std::string("'") + S + "'";
667 }
668 
669 
670 //===----------------------------------------------------------------------===//
671 // Methods on OptionalAmount.
672 //===----------------------------------------------------------------------===//
673 
674 ArgType
676  return Ctx.IntTy;
677 }
678 
679 //===----------------------------------------------------------------------===//
680 // Methods on LengthModifier.
681 //===----------------------------------------------------------------------===//
682 
683 const char *
685  switch (kind) {
686  case AsChar:
687  return "hh";
688  case AsShort:
689  return "h";
690  case AsShortLong:
691  return "hl";
692  case AsLong: // or AsWideChar
693  return "l";
694  case AsLongLong:
695  return "ll";
696  case AsQuad:
697  return "q";
698  case AsIntMax:
699  return "j";
700  case AsSizeT:
701  return "z";
702  case AsPtrDiff:
703  return "t";
704  case AsInt32:
705  return "I32";
706  case AsInt3264:
707  return "I";
708  case AsInt64:
709  return "I64";
710  case AsLongDouble:
711  return "L";
712  case AsAllocate:
713  return "a";
714  case AsMAllocate:
715  return "m";
716  case AsWide:
717  return "w";
718  case None:
719  return "";
720  }
721  return nullptr;
722 }
723 
724 //===----------------------------------------------------------------------===//
725 // Methods on ConversionSpecifier.
726 //===----------------------------------------------------------------------===//
727 
728 const char *ConversionSpecifier::toString() const {
729  switch (kind) {
730  case bArg: return "b";
731  case BArg: return "B";
732  case dArg: return "d";
733  case DArg: return "D";
734  case iArg: return "i";
735  case oArg: return "o";
736  case OArg: return "O";
737  case uArg: return "u";
738  case UArg: return "U";
739  case xArg: return "x";
740  case XArg: return "X";
741  case fArg: return "f";
742  case FArg: return "F";
743  case eArg: return "e";
744  case EArg: return "E";
745  case gArg: return "g";
746  case GArg: return "G";
747  case aArg: return "a";
748  case AArg: return "A";
749  case cArg: return "c";
750  case sArg: return "s";
751  case pArg: return "p";
752  case PArg:
753  return "P";
754  case nArg: return "n";
755  case PercentArg: return "%";
756  case ScanListArg: return "[";
757  case InvalidSpecifier: return nullptr;
758 
759  // POSIX unicode extensions.
760  case CArg: return "C";
761  case SArg: return "S";
762 
763  // Objective-C specific specifiers.
764  case ObjCObjArg: return "@";
765 
766  // FreeBSD kernel specific specifiers.
767  case FreeBSDbArg: return "b";
768  case FreeBSDDArg: return "D";
769  case FreeBSDrArg: return "r";
770  case FreeBSDyArg: return "y";
771 
772  // GlibC specific specifiers.
773  case PrintErrno: return "m";
774 
775  // MS specific specifiers.
776  case ZArg: return "Z";
777 
778  // ISO/IEC TR 18037 (fixed-point) specific specifiers.
779  case rArg:
780  return "r";
781  case RArg:
782  return "R";
783  case kArg:
784  return "k";
785  case KArg:
786  return "K";
787  }
788  return nullptr;
789 }
790 
791 std::optional<ConversionSpecifier>
794 
795  switch (getKind()) {
796  default:
797  return std::nullopt;
798  case DArg:
799  NewKind = dArg;
800  break;
801  case UArg:
802  NewKind = uArg;
803  break;
804  case OArg:
805  NewKind = oArg;
806  break;
807  }
808 
809  ConversionSpecifier FixedCS(*this);
810  FixedCS.setKind(NewKind);
811  return FixedCS;
812 }
813 
814 //===----------------------------------------------------------------------===//
815 // Methods on OptionalAmount.
816 //===----------------------------------------------------------------------===//
817 
818 void OptionalAmount::toString(raw_ostream &os) const {
819  switch (hs) {
820  case Invalid:
821  case NotSpecified:
822  return;
823  case Arg:
824  if (UsesDotPrefix)
825  os << ".";
826  if (usesPositionalArg())
827  os << "*" << getPositionalArgIndex() << "$";
828  else
829  os << "*";
830  break;
831  case Constant:
832  if (UsesDotPrefix)
833  os << ".";
834  os << amt;
835  break;
836  }
837 }
838 
840  const LangOptions &LO) const {
841  switch (LM.getKind()) {
843  return true;
844 
845  // Handle most integer flags
847  // Length modifier only applies to FP vectors.
848  if (LO.OpenCL && CS.isDoubleArg())
849  return !VectorNumElts.isInvalid();
850 
851  if (CS.isFixedPointArg())
852  return true;
853 
854  if (Target.getTriple().isOSMSVCRT()) {
855  switch (CS.getKind()) {
861  return true;
862  default:
863  break;
864  }
865  }
866  [[fallthrough]];
873  switch (CS.getKind()) {
886  return true;
889  return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
890  default:
891  return false;
892  }
893 
895  return LO.OpenCL && !VectorNumElts.isInvalid();
896 
897  // Handle 'l' flag
898  case LengthModifier::AsLong: // or AsWideChar
899  if (CS.isDoubleArg()) {
900  // Invalid for OpenCL FP scalars.
901  if (LO.OpenCL && VectorNumElts.isInvalid())
902  return false;
903  return true;
904  }
905 
906  if (CS.isFixedPointArg())
907  return true;
908 
909  switch (CS.getKind()) {
926  return true;
929  return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
930  default:
931  return false;
932  }
933 
935  switch (CS.getKind()) {
944  return true;
945  // GNU libc extension.
952  return !Target.getTriple().isOSDarwin() &&
953  !Target.getTriple().isOSWindows();
954  default:
955  return false;
956  }
957 
959  switch (CS.getKind()) {
963  return true;
964  default:
965  return false;
966  }
967 
969  switch (CS.getKind()) {
975  return true;
976  default:
977  return false;
978  }
982  switch (CS.getKind()) {
989  return Target.getTriple().isOSMSVCRT();
990  default:
991  return false;
992  }
994  switch (CS.getKind()) {
1000  return Target.getTriple().isOSMSVCRT();
1001  default:
1002  return false;
1003  }
1004  }
1005  llvm_unreachable("Invalid LengthModifier Kind!");
1006 }
1007 
1009  switch (LM.getKind()) {
1010  case LengthModifier::None:
1019  return true;
1027  case LengthModifier::AsShortLong: // ???
1028  return false;
1029  }
1030  llvm_unreachable("Invalid LengthModifier Kind!");
1031 }
1032 
1034  const LangOptions &LangOpt) const {
1035  switch (CS.getKind()) {
1060  return true;
1063  return LangOpt.ObjC;
1074  return false;
1079  return LangOpt.FixedPoint;
1080  }
1081  llvm_unreachable("Invalid ConversionSpecifier Kind!");
1082 }
1083 
1086  switch(CS.getKind()) {
1093  return false;
1094  default:
1095  return true;
1096  }
1097  }
1098  return true;
1099 }
1100 
1101 std::optional<LengthModifier>
1106  LengthModifier FixedLM(LM);
1108  return FixedLM;
1109  }
1110  }
1111 
1112  return std::nullopt;
1113 }
1114 
1116  LengthModifier &LM) {
1117  for (/**/; const auto *TT = QT->getAs<TypedefType>();
1118  QT = TT->getDecl()->getUnderlyingType()) {
1119  const TypedefNameDecl *Typedef = TT->getDecl();
1120  const IdentifierInfo *Identifier = Typedef->getIdentifier();
1121  if (Identifier->getName() == "size_t") {
1123  return true;
1124  } else if (Identifier->getName() == "ssize_t") {
1125  // Not C99, but common in Unix.
1127  return true;
1128  } else if (Identifier->getName() == "intmax_t") {
1130  return true;
1131  } else if (Identifier->getName() == "uintmax_t") {
1133  return true;
1134  } else if (Identifier->getName() == "ptrdiff_t") {
1136  return true;
1137  }
1138  }
1139  return false;
1140 }
StringRef Identifier
Definition: Format.cpp:2984
Defines the clang::LangOptions interface.
llvm::MachO::Target Target
Definition: MachO.h:50
__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:185
CanQualType IntTy
Definition: ASTContext.h:1103
Pointer to a block type.
Definition: Type.h:3361
This class is used for builtin types like 'int'.
Definition: Type.h:2989
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:5587
One of these records is kept for each identifier that is lexed.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:482
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
Represents a pointer to an Objective C object.
Definition: Type.h:7020
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3151
QualType getPointeeType() const
Definition: Type.h:3161
A (possibly-)qualified type.
Definition: Type.h:940
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:7444
Exposes information about the current target.
Definition: TargetInfo.h:218
bool isBlockPointerType() const
Definition: Type.h:7632
bool isVoidType() const
Definition: Type.h:7939
bool canDecayToPointerType() const
Determines whether this type can decay to a pointer type.
Definition: Type.h:8097
bool isVoidPointerType() const
Definition: Type.cpp:665
bool isPointerType() const
Definition: Type.h:7624
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isSaturatedFixedPointType() const
Return true if this is a saturated fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
Definition: Type.h:8008
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2185
const RecordType * getAsStructureType() const
Definition: Type.cpp:721
bool isObjCObjectPointerType() const
Definition: Type.h:7760
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8160
bool isNullPtrType() const
Definition: Type.h:7972
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3435
MatchKind
How well a given conversion specifier matches its argument.
Definition: FormatString.h:271
std::optional< ConversionSpecifier > getStandardSpecifier() const
void setFieldWidth(const OptionalAmount &Amt)
Definition: FormatString.h:472
bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const
static bool namedTypeToLengthModifier(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
std::optional< LengthModifier > getCorrectedLengthModifier() const
virtual void HandlePosition(const char *startPos, unsigned posLen)
Definition: FormatString.h:723
virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, PositionContext p)
Definition: FormatString.h:725
virtual void HandleZeroPosition(const char *startPos, unsigned posLen)
Definition: FormatString.h:728
virtual void HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:730
Represents the length modifier in a format string in scanf/printf.
Definition: FormatString.h:65
ArgType getArgType(ASTContext &Ctx) const
Defines the clang::TargetInfo interface.
constexpr XRayInstrMask None
Definition: XRayInstr.h:38
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...
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:65
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T