clang  20.0.0git
PrintfFormatString.cpp
Go to the documentation of this file.
1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Handling of format string in printf and friends. The structure of format
10 // strings for fprintf() are described in C99 7.19.6.1.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "FormatStringParsing.h"
15 #include "clang/AST/FormatString.h"
16 #include "clang/AST/OSLog.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "llvm/Support/Regex.h"
19 
26 
27 using namespace clang;
28 
31 
32 //===----------------------------------------------------------------------===//
33 // Methods for parsing format strings.
34 //===----------------------------------------------------------------------===//
35 
37 
39  const char *Start, const char *&Beg, const char *E,
40  unsigned *argIndex) {
41  if (argIndex) {
42  FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
43  } else {
44  const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
46  if (Amt.isInvalid())
47  return true;
48  FS.setPrecision(Amt);
49  }
50  return false;
51 }
52 
54  const char *FlagBeg, const char *E, bool Warn) {
55  StringRef Flag(FlagBeg, E - FlagBeg);
56  // Currently there is only one flag.
57  if (Flag == "tt") {
58  FS.setHasObjCTechnicalTerm(FlagBeg);
59  return false;
60  }
61  // Handle either the case of no flag or an invalid flag.
62  if (Warn) {
63  if (Flag == "")
64  H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg);
65  else
66  H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg);
67  }
68  return true;
69 }
70 
72  const char *&Beg,
73  const char *E,
74  unsigned &argIndex,
75  const LangOptions &LO,
76  const TargetInfo &Target,
77  bool Warn,
78  bool isFreeBSDKPrintf) {
79 
80  using namespace clang::analyze_format_string;
81  using namespace clang::analyze_printf;
82 
83  const char *I = Beg;
84  const char *Start = nullptr;
85  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
86 
87  // Look for a '%' character that indicates the start of a format specifier.
88  for ( ; I != E ; ++I) {
89  char c = *I;
90  if (c == '\0') {
91  // Detect spurious null characters, which are likely errors.
92  H.HandleNullChar(I);
93  return true;
94  }
95  if (c == '%') {
96  Start = I++; // Record the start of the format specifier.
97  break;
98  }
99  }
100 
101  // No format specifier found?
102  if (!Start)
103  return false;
104 
105  if (I == E) {
106  // No more characters left?
107  if (Warn)
108  H.HandleIncompleteSpecifier(Start, E - Start);
109  return true;
110  }
111 
112  PrintfSpecifier FS;
113  if (ParseArgPosition(H, FS, Start, I, E))
114  return true;
115 
116  if (I == E) {
117  // No more characters left?
118  if (Warn)
119  H.HandleIncompleteSpecifier(Start, E - Start);
120  return true;
121  }
122 
123  if (*I == '{') {
124  ++I;
125  unsigned char PrivacyFlags = 0;
126  StringRef MatchedStr;
127 
128  do {
129  StringRef Str(I, E - I);
130  std::string Match = "^[[:space:]]*"
131  "(private|public|sensitive|mask\\.[^[:space:],}]*)"
132  "[[:space:]]*(,|})";
133  llvm::Regex R(Match);
135 
136  if (R.match(Str, &Matches)) {
137  MatchedStr = Matches[1];
138  I += Matches[0].size();
139 
140  // Set the privacy flag if the privacy annotation in the
141  // comma-delimited segment is at least as strict as the privacy
142  // annotations in previous comma-delimited segments.
143  if (MatchedStr.starts_with("mask")) {
144  StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1);
145  unsigned Size = MaskType.size();
146  if (Warn && (Size == 0 || Size > 8))
147  H.handleInvalidMaskType(MaskType);
148  FS.setMaskType(MaskType);
149  } else if (MatchedStr == "sensitive")
151  else if (PrivacyFlags !=
153  MatchedStr == "private")
155  else if (PrivacyFlags == 0 && MatchedStr == "public")
157  } else {
158  size_t CommaOrBracePos =
159  Str.find_if([](char c) { return c == ',' || c == '}'; });
160 
161  if (CommaOrBracePos == StringRef::npos) {
162  // Neither a comma nor the closing brace was found.
163  if (Warn)
164  H.HandleIncompleteSpecifier(Start, E - Start);
165  return true;
166  }
167 
168  I += CommaOrBracePos + 1;
169  }
170  // Continue until the closing brace is found.
171  } while (*(I - 1) == ',');
172 
173  // Set the privacy flag.
174  switch (PrivacyFlags) {
175  case 0:
176  break;
178  FS.setIsPrivate(MatchedStr.data());
179  break;
181  FS.setIsPublic(MatchedStr.data());
182  break;
184  FS.setIsSensitive(MatchedStr.data());
185  break;
186  default:
187  llvm_unreachable("Unexpected privacy flag value");
188  }
189  }
190 
191  // Look for flags (if any).
192  bool hasMore = true;
193  for ( ; I != E; ++I) {
194  switch (*I) {
195  default: hasMore = false; break;
196  case '\'':
197  // FIXME: POSIX specific. Always accept?
198  FS.setHasThousandsGrouping(I);
199  break;
200  case '-': FS.setIsLeftJustified(I); break;
201  case '+': FS.setHasPlusPrefix(I); break;
202  case ' ': FS.setHasSpacePrefix(I); break;
203  case '#': FS.setHasAlternativeForm(I); break;
204  case '0': FS.setHasLeadingZeros(I); break;
205  }
206  if (!hasMore)
207  break;
208  }
209 
210  if (I == E) {
211  // No more characters left?
212  if (Warn)
213  H.HandleIncompleteSpecifier(Start, E - Start);
214  return true;
215  }
216 
217  // Look for the field width (if any).
218  if (ParseFieldWidth(H, FS, Start, I, E,
219  FS.usesPositionalArg() ? nullptr : &argIndex))
220  return true;
221 
222  if (I == E) {
223  // No more characters left?
224  if (Warn)
225  H.HandleIncompleteSpecifier(Start, E - Start);
226  return true;
227  }
228 
229  // Look for the precision (if any).
230  if (*I == '.') {
231  ++I;
232  if (I == E) {
233  if (Warn)
234  H.HandleIncompleteSpecifier(Start, E - Start);
235  return true;
236  }
237 
238  if (ParsePrecision(H, FS, Start, I, E,
239  FS.usesPositionalArg() ? nullptr : &argIndex))
240  return true;
241 
242  if (I == E) {
243  // No more characters left?
244  if (Warn)
245  H.HandleIncompleteSpecifier(Start, E - Start);
246  return true;
247  }
248  }
249 
250  if (ParseVectorModifier(H, FS, I, E, LO))
251  return true;
252 
253  // Look for the length modifier.
254  if (ParseLengthModifier(FS, I, E, LO) && I == E) {
255  // No more characters left?
256  if (Warn)
257  H.HandleIncompleteSpecifier(Start, E - Start);
258  return true;
259  }
260 
261  // Look for the Objective-C modifier flags, if any.
262  // We parse these here, even if they don't apply to
263  // the conversion specifier, and then emit an error
264  // later if the conversion specifier isn't '@'. This
265  // enables better recovery, and we don't know if
266  // these flags are applicable until later.
267  const char *ObjCModifierFlagsStart = nullptr,
268  *ObjCModifierFlagsEnd = nullptr;
269  if (*I == '[') {
270  ObjCModifierFlagsStart = I;
271  ++I;
272  auto flagStart = I;
273  for (;; ++I) {
274  ObjCModifierFlagsEnd = I;
275  if (I == E) {
276  if (Warn)
277  H.HandleIncompleteSpecifier(Start, E - Start);
278  return true;
279  }
280  // Did we find the closing ']'?
281  if (*I == ']') {
282  if (ParseObjCFlags(H, FS, flagStart, I, Warn))
283  return true;
284  ++I;
285  break;
286  }
287  // There are no separators defined yet for multiple
288  // Objective-C modifier flags. When those are
289  // defined, this is the place to check.
290  }
291  }
292 
293  if (*I == '\0') {
294  // Detect spurious null characters, which are likely errors.
295  H.HandleNullChar(I);
296  return true;
297  }
298 
299  // Finally, look for the conversion specifier.
300  const char *conversionPosition = I++;
302  switch (*conversionPosition) {
303  default:
304  break;
305  // C99: 7.19.6.1 (section 8).
306  case '%': k = ConversionSpecifier::PercentArg; break;
307  case 'A': k = ConversionSpecifier::AArg; break;
308  case 'E': k = ConversionSpecifier::EArg; break;
309  case 'F': k = ConversionSpecifier::FArg; break;
310  case 'G': k = ConversionSpecifier::GArg; break;
311  case 'X': k = ConversionSpecifier::XArg; break;
312  case 'a': k = ConversionSpecifier::aArg; break;
313  case 'c': k = ConversionSpecifier::cArg; break;
314  case 'd': k = ConversionSpecifier::dArg; break;
315  case 'e': k = ConversionSpecifier::eArg; break;
316  case 'f': k = ConversionSpecifier::fArg; break;
317  case 'g': k = ConversionSpecifier::gArg; break;
318  case 'i': k = ConversionSpecifier::iArg; break;
319  case 'n':
320  // Not handled, but reserved in OpenCL.
321  if (!LO.OpenCL)
323  break;
324  case 'o': k = ConversionSpecifier::oArg; break;
325  case 'p': k = ConversionSpecifier::pArg; break;
326  case 's': k = ConversionSpecifier::sArg; break;
327  case 'u': k = ConversionSpecifier::uArg; break;
328  case 'x': k = ConversionSpecifier::xArg; break;
329  // C23.
330  case 'b':
331  if (isFreeBSDKPrintf)
332  k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
333  else
335  break;
336  case 'B': k = ConversionSpecifier::BArg; break;
337  // POSIX specific.
338  case 'C': k = ConversionSpecifier::CArg; break;
339  case 'S': k = ConversionSpecifier::SArg; break;
340  // Apple extension for os_log
341  case 'P':
343  break;
344  // Objective-C.
345  case '@': k = ConversionSpecifier::ObjCObjArg; break;
346  // Glibc specific.
347  case 'm': k = ConversionSpecifier::PrintErrno; break;
348  case 'r':
349  if (isFreeBSDKPrintf)
351  else if (LO.FixedPoint)
353  break;
354  case 'y':
355  if (isFreeBSDKPrintf)
357  break;
358  // Apple-specific.
359  case 'D':
360  if (isFreeBSDKPrintf)
361  k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
362  else if (Target.getTriple().isOSDarwin())
364  break;
365  case 'O':
366  if (Target.getTriple().isOSDarwin())
368  break;
369  case 'U':
370  if (Target.getTriple().isOSDarwin())
372  break;
373  // MS specific.
374  case 'Z':
375  if (Target.getTriple().isOSMSVCRT())
377  break;
378  // ISO/IEC TR 18037 (fixed-point) specific.
379  // NOTE: 'r' is handled up above since FreeBSD also supports %r.
380  case 'k':
381  if (LO.FixedPoint)
383  break;
384  case 'K':
385  if (LO.FixedPoint)
387  break;
388  case 'R':
389  if (LO.FixedPoint)
391  break;
392  }
393 
394  // Check to see if we used the Objective-C modifier flags with
395  // a conversion specifier other than '@'.
398  ObjCModifierFlagsStart) {
399  H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
400  ObjCModifierFlagsEnd + 1,
401  conversionPosition);
402  return true;
403  }
404 
405  PrintfConversionSpecifier CS(conversionPosition, k);
406  FS.setConversionSpecifier(CS);
407  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
408  FS.setArgIndex(argIndex++);
409  // FreeBSD kernel specific.
412  argIndex++;
413 
415  unsigned Len = I - Start;
416  if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
417  CS.setEndScanList(Start + Len);
418  FS.setConversionSpecifier(CS);
419  }
420  // Assume the conversion takes one argument.
421  return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
422  }
423  return PrintfSpecifierResult(Start, FS);
424 }
425 
427  const char *I,
428  const char *E,
429  const LangOptions &LO,
430  const TargetInfo &Target,
431  bool isFreeBSDKPrintf) {
432 
433  unsigned argIndex = 0;
434 
435  // Keep looking for a format specifier until we have exhausted the string.
436  while (I != E) {
437  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
438  LO, Target, true,
439  isFreeBSDKPrintf);
440  // Did a fail-stop error of any kind occur when parsing the specifier?
441  // If so, don't do any more processing.
442  if (FSR.shouldStop())
443  return true;
444  // Did we exhaust the string or encounter an error that
445  // we can recover from?
446  if (!FSR.hasValue())
447  continue;
448  // We have a format specifier. Pass it to the callback.
449  if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
450  I - FSR.getStart(), Target))
451  return true;
452  }
453  assert(I == E && "Format string not exhausted");
454  return false;
455 }
456 
458  const char *E,
459  const LangOptions &LO,
460  const TargetInfo &Target) {
461 
462  unsigned argIndex = 0;
463 
464  // Keep looking for a %s format specifier until we have exhausted the string.
466  while (I != E) {
467  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
468  LO, Target, false,
469  false);
470  // Did a fail-stop error of any kind occur when parsing the specifier?
471  // If so, don't do any more processing.
472  if (FSR.shouldStop())
473  return false;
474  // Did we exhaust the string or encounter an error that
475  // we can recover from?
476  if (!FSR.hasValue())
477  continue;
478  const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
479  // Return true if this a %s format specifier.
480  if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
481  return true;
482  }
483  return false;
484 }
485 
487  const char *Begin, const char *End, const LangOptions &LO,
488  const TargetInfo &Target) {
489  unsigned ArgIndex = 0;
490  // Keep looking for a formatting specifier until we have exhausted the string.
492  while (Begin != End) {
493  const PrintfSpecifierResult &FSR =
494  ParsePrintfSpecifier(H, Begin, End, ArgIndex, LO, Target, false, false);
495  if (FSR.shouldStop())
496  break;
497  if (FSR.hasValue())
498  return true;
499  }
500  return false;
501 }
502 
503 //===----------------------------------------------------------------------===//
504 // Methods on PrintfSpecifier.
505 //===----------------------------------------------------------------------===//
506 
507 ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
508  bool IsObjCLiteral) const {
509  if (CS.getKind() == ConversionSpecifier::cArg)
510  switch (LM.getKind()) {
512  return Ctx.IntTy;
515  return ArgType(ArgType::WIntTy, "wint_t");
517  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
518  return Ctx.IntTy;
519  [[fallthrough]];
520  default:
521  return ArgType::Invalid();
522  }
523 
524  if (CS.isIntArg())
525  switch (LM.getKind()) {
527  // GNU extension.
528  return Ctx.LongLongTy;
531  return Ctx.IntTy;
533  return ArgType(Ctx.IntTy, "__int32");
535  return ArgType::AnyCharTy;
536  case LengthModifier::AsShort: return Ctx.ShortTy;
537  case LengthModifier::AsLong: return Ctx.LongTy;
540  return Ctx.LongLongTy;
542  return ArgType(Ctx.LongLongTy, "__int64");
544  return ArgType(Ctx.getIntMaxType(), "intmax_t");
546  return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
548  return Ctx.getTargetInfo().getTriple().isArch64Bit()
549  ? ArgType(Ctx.LongLongTy, "__int64")
550  : ArgType(Ctx.IntTy, "__int32");
552  return ArgType::makePtrdiffT(
553  ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
557  return ArgType::Invalid();
558  }
559 
560  if (CS.isUIntArg())
561  switch (LM.getKind()) {
563  // GNU extension.
564  return Ctx.UnsignedLongLongTy;
567  return Ctx.UnsignedIntTy;
569  return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
570  case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
571  case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
572  case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
575  return Ctx.UnsignedLongLongTy;
577  return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
579  return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
581  return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
583  return Ctx.getTargetInfo().getTriple().isArch64Bit()
584  ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
585  : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
587  return ArgType::makePtrdiffT(
588  ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
592  return ArgType::Invalid();
593  }
594 
595  if (CS.isDoubleArg()) {
596  if (!VectorNumElts.isInvalid()) {
597  switch (LM.getKind()) {
599  return Ctx.HalfTy;
601  return Ctx.FloatTy;
603  default:
604  return Ctx.DoubleTy;
605  }
606  }
607 
608  if (LM.getKind() == LengthModifier::AsLongDouble)
609  return Ctx.LongDoubleTy;
610  return Ctx.DoubleTy;
611  }
612 
613  if (CS.getKind() == ConversionSpecifier::nArg) {
614  switch (LM.getKind()) {
616  return ArgType::PtrTo(Ctx.IntTy);
618  return ArgType::PtrTo(Ctx.SignedCharTy);
620  return ArgType::PtrTo(Ctx.ShortTy);
622  return ArgType::PtrTo(Ctx.LongTy);
625  return ArgType::PtrTo(Ctx.LongLongTy);
627  return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
629  return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
631  return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
633  return ArgType(); // FIXME: Is this a known extension?
640  return ArgType::Invalid();
642  llvm_unreachable("only used for OpenCL which doesn not handle nArg");
643  }
644  }
645 
646  if (CS.isFixedPointArg() && !Ctx.getLangOpts().FixedPoint)
647  return ArgType::Invalid();
648 
649  switch (CS.getKind()) {
651  if (LM.getKind() == LengthModifier::AsWideChar) {
652  if (IsObjCLiteral)
654  "const unichar *");
655  return ArgType(ArgType::WCStrTy, "wchar_t *");
656  }
657  if (LM.getKind() == LengthModifier::AsWide)
658  return ArgType(ArgType::WCStrTy, "wchar_t *");
659  return ArgType::CStrTy;
661  if (IsObjCLiteral)
663  "const unichar *");
664  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
665  LM.getKind() == LengthModifier::AsShort)
666  return ArgType::CStrTy;
667  return ArgType(ArgType::WCStrTy, "wchar_t *");
669  if (IsObjCLiteral)
670  return ArgType(Ctx.UnsignedShortTy, "unichar");
671  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
672  LM.getKind() == LengthModifier::AsShort)
673  return Ctx.IntTy;
674  return ArgType(Ctx.WideCharTy, "wchar_t");
677  return ArgType::CPointerTy;
679  return ArgType::ObjCPointerTy;
681  switch (LM.getKind()) {
683  return Ctx.AccumTy;
685  return Ctx.ShortAccumTy;
687  return Ctx.LongAccumTy;
688  default:
689  return ArgType::Invalid();
690  }
692  switch (LM.getKind()) {
694  return Ctx.UnsignedAccumTy;
696  return Ctx.UnsignedShortAccumTy;
698  return Ctx.UnsignedLongAccumTy;
699  default:
700  return ArgType::Invalid();
701  }
703  switch (LM.getKind()) {
705  return Ctx.FractTy;
707  return Ctx.ShortFractTy;
709  return Ctx.LongFractTy;
710  default:
711  return ArgType::Invalid();
712  }
714  switch (LM.getKind()) {
716  return Ctx.UnsignedFractTy;
718  return Ctx.UnsignedShortFractTy;
720  return Ctx.UnsignedLongFractTy;
721  default:
722  return ArgType::Invalid();
723  }
724  default:
725  break;
726  }
727 
728  // FIXME: Handle other cases.
729  return ArgType();
730 }
731 
732 
733 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
734  bool IsObjCLiteral) const {
735  const PrintfConversionSpecifier &CS = getConversionSpecifier();
736 
737  if (!CS.consumesDataArgument())
738  return ArgType::Invalid();
739 
740  ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
741  if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
742  return ScalarTy;
743 
744  return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
745 }
746 
747 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
748  ASTContext &Ctx, bool IsObjCLiteral) {
749  // %n is different from other conversion specifiers; don't try to fix it.
750  if (CS.getKind() == ConversionSpecifier::nArg)
751  return false;
752 
753  // Handle Objective-C objects first. Note that while the '%@' specifier will
754  // not warn for structure pointer or void pointer arguments (because that's
755  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
756  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
757  if (QT->isObjCRetainableType()) {
758  if (!IsObjCLiteral)
759  return false;
760 
762 
763  // Disable irrelevant flags
764  HasThousandsGrouping = false;
765  HasPlusPrefix = false;
766  HasSpacePrefix = false;
767  HasAlternativeForm = false;
768  HasLeadingZeroes = false;
769  Precision.setHowSpecified(OptionalAmount::NotSpecified);
770  LM.setKind(LengthModifier::None);
771 
772  return true;
773  }
774 
775  // Handle strings next (char *, wchar_t *)
776  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
777  CS.setKind(ConversionSpecifier::sArg);
778 
779  // Disable irrelevant flags
780  HasAlternativeForm = false;
781  HasLeadingZeroes = false;
782 
783  // Set the long length modifier for wide characters
784  if (QT->getPointeeType()->isWideCharType())
785  LM.setKind(LengthModifier::AsWideChar);
786  else
787  LM.setKind(LengthModifier::None);
788 
789  return true;
790  }
791 
792  // If it's an enum, get its underlying type.
793  if (const EnumType *ETy = QT->getAs<EnumType>())
794  QT = ETy->getDecl()->getIntegerType();
795 
796  const BuiltinType *BT = QT->getAs<BuiltinType>();
797  if (!BT) {
798  const VectorType *VT = QT->getAs<VectorType>();
799  if (VT) {
800  QT = VT->getElementType();
801  BT = QT->getAs<BuiltinType>();
802  VectorNumElts = OptionalAmount(VT->getNumElements());
803  }
804  }
805 
806  // We can only work with builtin types.
807  if (!BT)
808  return false;
809 
810  // Set length modifier
811  switch (BT->getKind()) {
812  case BuiltinType::Bool:
813  case BuiltinType::WChar_U:
814  case BuiltinType::WChar_S:
815  case BuiltinType::Char8: // FIXME: Treat like 'char'?
816  case BuiltinType::Char16:
817  case BuiltinType::Char32:
818  case BuiltinType::UInt128:
819  case BuiltinType::Int128:
820  case BuiltinType::Half:
821  case BuiltinType::BFloat16:
822  case BuiltinType::Float16:
823  case BuiltinType::Float128:
824  case BuiltinType::Ibm128:
825  case BuiltinType::ShortAccum:
826  case BuiltinType::Accum:
827  case BuiltinType::LongAccum:
828  case BuiltinType::UShortAccum:
829  case BuiltinType::UAccum:
830  case BuiltinType::ULongAccum:
831  case BuiltinType::ShortFract:
832  case BuiltinType::Fract:
833  case BuiltinType::LongFract:
834  case BuiltinType::UShortFract:
835  case BuiltinType::UFract:
836  case BuiltinType::ULongFract:
837  case BuiltinType::SatShortAccum:
838  case BuiltinType::SatAccum:
839  case BuiltinType::SatLongAccum:
840  case BuiltinType::SatUShortAccum:
841  case BuiltinType::SatUAccum:
842  case BuiltinType::SatULongAccum:
843  case BuiltinType::SatShortFract:
844  case BuiltinType::SatFract:
845  case BuiltinType::SatLongFract:
846  case BuiltinType::SatUShortFract:
847  case BuiltinType::SatUFract:
848  case BuiltinType::SatULongFract:
849  // Various types which are non-trivial to correct.
850  return false;
851 
852 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
853  case BuiltinType::Id:
854 #include "clang/Basic/OpenCLImageTypes.def"
855 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
856  case BuiltinType::Sampled##Id:
857 #define IMAGE_WRITE_TYPE(Type, Id, Ext)
858 #define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)
859 #include "clang/Basic/OpenCLImageTypes.def"
860 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
861  case BuiltinType::Id:
862 #include "clang/Basic/OpenCLExtensionTypes.def"
863 #define SVE_TYPE(Name, Id, SingletonId) \
864  case BuiltinType::Id:
865 #include "clang/Basic/AArch64SVEACLETypes.def"
866 #define PPC_VECTOR_TYPE(Name, Id, Size) \
867  case BuiltinType::Id:
868 #include "clang/Basic/PPCTypes.def"
869 #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
870 #include "clang/Basic/RISCVVTypes.def"
871 #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
872 #include "clang/Basic/WebAssemblyReferenceTypes.def"
873 #define AMDGPU_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
874 #include "clang/Basic/AMDGPUTypes.def"
875 #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
876 #include "clang/Basic/HLSLIntangibleTypes.def"
877 #define SIGNED_TYPE(Id, SingletonId)
878 #define UNSIGNED_TYPE(Id, SingletonId)
879 #define FLOATING_TYPE(Id, SingletonId)
880 #define BUILTIN_TYPE(Id, SingletonId) \
881  case BuiltinType::Id:
882 #include "clang/AST/BuiltinTypes.def"
883  // Misc other stuff which doesn't make sense here.
884  return false;
885 
886  case BuiltinType::UInt:
887  case BuiltinType::Int:
888  case BuiltinType::Float:
889  LM.setKind(VectorNumElts.isInvalid() ?
891  break;
892  case BuiltinType::Double:
893  LM.setKind(VectorNumElts.isInvalid() ?
895  break;
896  case BuiltinType::Char_U:
897  case BuiltinType::UChar:
898  case BuiltinType::Char_S:
899  case BuiltinType::SChar:
900  LM.setKind(LengthModifier::AsChar);
901  break;
902 
903  case BuiltinType::Short:
904  case BuiltinType::UShort:
905  LM.setKind(LengthModifier::AsShort);
906  break;
907 
908  case BuiltinType::Long:
909  case BuiltinType::ULong:
910  LM.setKind(LengthModifier::AsLong);
911  break;
912 
913  case BuiltinType::LongLong:
914  case BuiltinType::ULongLong:
915  LM.setKind(LengthModifier::AsLongLong);
916  break;
917 
918  case BuiltinType::LongDouble:
919  LM.setKind(LengthModifier::AsLongDouble);
920  break;
921  }
922 
923  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
924  if (LangOpt.C99 || LangOpt.CPlusPlus11)
925  namedTypeToLengthModifier(QT, LM);
926 
927  // If fixing the length modifier was enough, we might be done.
928  if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
929  // If we're going to offer a fix anyway, make sure the sign matches.
930  switch (CS.getKind()) {
933  if (QT->isSignedIntegerType())
935  break;
939  if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
941  break;
942  default:
943  // Other specifiers do not have signed/unsigned variants.
944  break;
945  }
946 
947  const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
948  if (ATR.isValid() && ATR.matchesType(Ctx, QT))
949  return true;
950  }
951 
952  // Set conversion specifier and disable any flags which do not apply to it.
953  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
954  if (!QT->getAs<TypedefType>() && QT->isCharType()) {
955  CS.setKind(ConversionSpecifier::cArg);
956  LM.setKind(LengthModifier::None);
957  Precision.setHowSpecified(OptionalAmount::NotSpecified);
958  HasAlternativeForm = false;
959  HasLeadingZeroes = false;
960  HasPlusPrefix = false;
961  }
962  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
963  else if (QT->isRealFloatingType()) {
964  CS.setKind(ConversionSpecifier::fArg);
965  } else if (QT->isSignedIntegerType()) {
966  CS.setKind(ConversionSpecifier::dArg);
967  HasAlternativeForm = false;
968  } else if (QT->isUnsignedIntegerType()) {
969  CS.setKind(ConversionSpecifier::uArg);
970  HasAlternativeForm = false;
971  HasPlusPrefix = false;
972  } else {
973  llvm_unreachable("Unexpected type");
974  }
975 
976  return true;
977 }
978 
979 void PrintfSpecifier::toString(raw_ostream &os) const {
980  // Whilst some features have no defined order, we are using the order
981  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
982  os << "%";
983 
984  // Positional args
985  if (usesPositionalArg()) {
986  os << getPositionalArgIndex() << "$";
987  }
988 
989  // Conversion flags
990  if (IsLeftJustified) os << "-";
991  if (HasPlusPrefix) os << "+";
992  if (HasSpacePrefix) os << " ";
993  if (HasAlternativeForm) os << "#";
994  if (HasLeadingZeroes) os << "0";
995 
996  // Minimum field width
997  FieldWidth.toString(os);
998  // Precision
999  Precision.toString(os);
1000 
1001  // Vector modifier
1002  if (!VectorNumElts.isInvalid())
1003  os << 'v' << VectorNumElts.getConstantAmount();
1004 
1005  // Length modifier
1006  os << LM.toString();
1007  // Conversion specifier
1008  os << CS.toString();
1009 }
1010 
1011 bool PrintfSpecifier::hasValidPlusPrefix() const {
1012  if (!HasPlusPrefix)
1013  return true;
1014 
1015  // The plus prefix only makes sense for signed conversions
1016  switch (CS.getKind()) {
1032  return true;
1033 
1034  default:
1035  return false;
1036  }
1037 }
1038 
1039 bool PrintfSpecifier::hasValidAlternativeForm() const {
1040  if (!HasAlternativeForm)
1041  return true;
1042 
1043  // Alternate form flag only valid with the bBoxXaAeEfFgGrRkK conversions
1044  switch (CS.getKind()) {
1065  return true;
1066 
1067  default:
1068  return false;
1069  }
1070 }
1071 
1072 bool PrintfSpecifier::hasValidLeadingZeros() const {
1073  if (!HasLeadingZeroes)
1074  return true;
1075 
1076  // Leading zeroes flag only valid with the bBdiouxXaAeEfFgGrRkK conversions
1077  switch (CS.getKind()) {
1103  return true;
1104 
1105  default:
1106  return false;
1107  }
1108 }
1109 
1110 bool PrintfSpecifier::hasValidSpacePrefix() const {
1111  if (!HasSpacePrefix)
1112  return true;
1113 
1114  // The space prefix only makes sense for signed conversions
1115  switch (CS.getKind()) {
1131  return true;
1132 
1133  default:
1134  return false;
1135  }
1136 }
1137 
1138 bool PrintfSpecifier::hasValidLeftJustified() const {
1139  if (!IsLeftJustified)
1140  return true;
1141 
1142  // The left justified flag is valid for all conversions except n
1143  switch (CS.getKind()) {
1145  return false;
1146 
1147  default:
1148  return true;
1149  }
1150 }
1151 
1152 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
1153  if (!HasThousandsGrouping)
1154  return true;
1155 
1156  switch (CS.getKind()) {
1166  return true;
1167  default:
1168  return false;
1169  }
1170 }
1171 
1172 bool PrintfSpecifier::hasValidPrecision() const {
1173  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
1174  return true;
1175 
1176  // Precision is only valid with the bBdiouxXaAeEfFgGsPrRkK conversions
1177  switch (CS.getKind()) {
1205  return true;
1206 
1207  default:
1208  return false;
1209  }
1210 }
1211 bool PrintfSpecifier::hasValidFieldWidth() const {
1212  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1213  return true;
1214 
1215  // The field width is valid for all conversions except n
1216  switch (CS.getKind()) {
1218  return false;
1219 
1220  default:
1221  return true;
1222  }
1223 }
Expr * E
llvm::MachO::Target Target
Definition: MachO.h:51
clang::analyze_format_string::SpecifierResult< PrintfSpecifier > PrintfSpecifierResult
static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, const char *Start, const char *&Beg, const char *E, unsigned *argIndex)
static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, const char *&Beg, const char *E, unsigned &argIndex, const LangOptions &LO, const TargetInfo &Target, bool Warn, bool isFreeBSDKPrintf)
static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS, const char *FlagBeg, const char *E, bool Warn)
SourceLocation End
SourceLocation Begin
__device__ __2f16 float c
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
CanQualType AccumTy
Definition: ASTContext.h:1132
CanQualType LongTy
Definition: ASTContext.h:1128
CanQualType UnsignedShortAccumTy
Definition: ASTContext.h:1134
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
CanQualType ShortAccumTy
Definition: ASTContext.h:1132
CanQualType FloatTy
Definition: ASTContext.h:1131
CanQualType DoubleTy
Definition: ASTContext.h:1131
CanQualType getIntMaxType() const
Return the unique type for "intmax_t" (C99 7.18.1.5), defined in <stdint.h>.
CanQualType LongDoubleTy
Definition: ASTContext.h:1131
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType UnsignedLongFractTy
Definition: ASTContext.h:1136
CanQualType WideCharTy
Definition: ASTContext.h:1123
const LangOptions & getLangOpts() const
Definition: ASTContext.h:797
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
CanQualType UnsignedFractTy
Definition: ASTContext.h:1136
CanQualType UnsignedLongTy
Definition: ASTContext.h:1129
CanQualType UnsignedLongAccumTy
Definition: ASTContext.h:1134
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType ShortFractTy
Definition: ASTContext.h:1135
CanQualType IntTy
Definition: ASTContext.h:1128
CanQualType SignedCharTy
Definition: ASTContext.h:1128
CanQualType UnsignedCharTy
Definition: ASTContext.h:1129
CanQualType UnsignedShortFractTy
Definition: ASTContext.h:1136
CanQualType UnsignedIntTy
Definition: ASTContext.h:1129
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:1130
CanQualType UnsignedShortTy
Definition: ASTContext.h:1129
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:779
CanQualType ShortTy
Definition: ASTContext.h:1128
CanQualType FractTy
Definition: ASTContext.h:1135
CanQualType LongAccumTy
Definition: ASTContext.h:1133
CanQualType LongFractTy
Definition: ASTContext.h:1135
CanQualType LongLongTy
Definition: ASTContext.h:1128
CanQualType getSignedSizeType() const
Return the unique signed counterpart of the integer type corresponding to size_t.
CanQualType getUIntMaxType() const
Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in <stdint.h>.
CanQualType HalfTy
Definition: ASTContext.h:1143
CanQualType UnsignedAccumTy
Definition: ASTContext.h:1134
This class is used for builtin types like 'int'.
Definition: Type.h:3029
Kind getKind() const
Definition: Type.h:3081
QualType withConst() const
Retrieves a version of this type with const applied.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:6001
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:480
A (possibly-)qualified type.
Definition: Type.h:941
Exposes information about the current target.
Definition: TargetInfo.h:218
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1256
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition: Type.cpp:2146
bool isCharType() const
Definition: Type.cpp:2089
bool isPointerType() const
Definition: Type.h:8013
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition: Type.cpp:2125
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2266
bool isWideCharType() const
Definition: Type.cpp:2098
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Definition: Type.cpp:2196
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8568
bool isObjCRetainableType() const
Definition: Type.cpp:4961
Represents a GCC generic vector type.
Definition: Type.h:4031
unsigned getNumElements() const
Definition: Type.h:4046
QualType getElementType() const
Definition: Type.h:4045
static ArgType makePtrdiffT(const ArgType &A)
Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t type.
Definition: FormatString.h:334
static ArgType PtrTo(const ArgType &A)
Create an ArgType which corresponds to the type pointer to A.
Definition: FormatString.h:318
ArgType makeVectorType(ASTContext &C, unsigned NumElts) const
static ArgType makeSizeT(const ArgType &A)
Create an ArgType which corresponds to the size_t/ssize_t type.
Definition: FormatString.h:326
MatchKind matchesType(ASTContext &C, QualType argTy) const
virtual bool HandleInvalidPrintfConversionSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:744
virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart, const char *flagsEnd, const char *conversionPosition)
Definition: FormatString.h:739
virtual void HandleInvalidObjCModifierFlag(const char *startFlag, unsigned flagLen)
Definition: FormatString.h:736
virtual void HandleNullChar(const char *nullCharacter)
Definition: FormatString.h:721
virtual void handleInvalidMaskType(StringRef MaskType)
Handle mask types whose sizes are not between one and eight bytes.
Definition: FormatString.h:759
virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen, const TargetInfo &Target)
Definition: FormatString.h:751
virtual void HandleEmptyObjCModifierFlag(const char *startFlags, unsigned flagsLen)
Definition: FormatString.h:733
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
Defines the clang::TargetInfo interface.
Common components of both fprintf and fscanf format strings.
Definition: FormatString.h:30
bool parseFormatStringHasFormattingSpecifiers(const char *Begin, const char *End, const LangOptions &LO, const TargetInfo &Target)
Return true if the given string has at least one formatting specifier.
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 ParseNonPositionAmount(const char *&Beg, const char *E, unsigned &argIndex)
bool ParsePrintfString(FormatStringHandler &H, const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target, bool isFreeBSDKPrintf)
bool 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 ParseFormatStringHasSArg(const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target)
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...
Pieces specific to fprintf format strings.
Definition: FormatString.h:499
std::string toString(const til::SExpr *E)
The JSON file list parser is used to communicate input to InstallAPI.