clang  11.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.startswith("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.equals("sensitive"))
151  else if (PrivacyFlags !=
153  MatchedStr.equals("private"))
155  else if (PrivacyFlags == 0 && MatchedStr.equals("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?
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  // POSIX specific.
330  case 'C': k = ConversionSpecifier::CArg; break;
331  case 'S': k = ConversionSpecifier::SArg; break;
332  // Apple extension for os_log
333  case 'P':
335  break;
336  // Objective-C.
337  case '@': k = ConversionSpecifier::ObjCObjArg; break;
338  // Glibc specific.
339  case 'm': k = ConversionSpecifier::PrintErrno; break;
340  // FreeBSD kernel specific.
341  case 'b':
342  if (isFreeBSDKPrintf)
343  k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
344  break;
345  case 'r':
346  if (isFreeBSDKPrintf)
348  break;
349  case 'y':
350  if (isFreeBSDKPrintf)
352  break;
353  // Apple-specific.
354  case 'D':
355  if (isFreeBSDKPrintf)
356  k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
357  else if (Target.getTriple().isOSDarwin())
359  break;
360  case 'O':
361  if (Target.getTriple().isOSDarwin())
363  break;
364  case 'U':
365  if (Target.getTriple().isOSDarwin())
367  break;
368  // MS specific.
369  case 'Z':
370  if (Target.getTriple().isOSMSVCRT())
372  break;
373  }
374 
375  // Check to see if we used the Objective-C modifier flags with
376  // a conversion specifier other than '@'.
379  ObjCModifierFlagsStart) {
380  H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
381  ObjCModifierFlagsEnd + 1,
382  conversionPosition);
383  return true;
384  }
385 
386  PrintfConversionSpecifier CS(conversionPosition, k);
387  FS.setConversionSpecifier(CS);
388  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
389  FS.setArgIndex(argIndex++);
390  // FreeBSD kernel specific.
393  argIndex++;
394 
396  unsigned Len = I - Start;
397  if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
398  CS.setEndScanList(Start + Len);
399  FS.setConversionSpecifier(CS);
400  }
401  // Assume the conversion takes one argument.
402  return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
403  }
404  return PrintfSpecifierResult(Start, FS);
405 }
406 
408  const char *I,
409  const char *E,
410  const LangOptions &LO,
411  const TargetInfo &Target,
412  bool isFreeBSDKPrintf) {
413 
414  unsigned argIndex = 0;
415 
416  // Keep looking for a format specifier until we have exhausted the string.
417  while (I != E) {
418  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
419  LO, Target, true,
420  isFreeBSDKPrintf);
421  // Did a fail-stop error of any kind occur when parsing the specifier?
422  // If so, don't do any more processing.
423  if (FSR.shouldStop())
424  return true;
425  // Did we exhaust the string or encounter an error that
426  // we can recover from?
427  if (!FSR.hasValue())
428  continue;
429  // We have a format specifier. Pass it to the callback.
430  if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
431  I - FSR.getStart()))
432  return true;
433  }
434  assert(I == E && "Format string not exhausted");
435  return false;
436 }
437 
439  const char *E,
440  const LangOptions &LO,
441  const TargetInfo &Target) {
442 
443  unsigned argIndex = 0;
444 
445  // Keep looking for a %s format specifier until we have exhausted the string.
447  while (I != E) {
448  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
449  LO, Target, false,
450  false);
451  // Did a fail-stop error of any kind occur when parsing the specifier?
452  // If so, don't do any more processing.
453  if (FSR.shouldStop())
454  return false;
455  // Did we exhaust the string or encounter an error that
456  // we can recover from?
457  if (!FSR.hasValue())
458  continue;
459  const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
460  // Return true if this a %s format specifier.
461  if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
462  return true;
463  }
464  return false;
465 }
466 
468  const char *Begin, const char *End, const LangOptions &LO,
469  const TargetInfo &Target) {
470  unsigned ArgIndex = 0;
471  // Keep looking for a formatting specifier until we have exhausted the string.
473  while (Begin != End) {
474  const PrintfSpecifierResult &FSR =
475  ParsePrintfSpecifier(H, Begin, End, ArgIndex, LO, Target, false, false);
476  if (FSR.shouldStop())
477  break;
478  if (FSR.hasValue())
479  return true;
480  }
481  return false;
482 }
483 
484 //===----------------------------------------------------------------------===//
485 // Methods on PrintfSpecifier.
486 //===----------------------------------------------------------------------===//
487 
488 ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
489  bool IsObjCLiteral) const {
490  if (CS.getKind() == ConversionSpecifier::cArg)
491  switch (LM.getKind()) {
493  return Ctx.IntTy;
496  return ArgType(ArgType::WIntTy, "wint_t");
498  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
499  return Ctx.IntTy;
500  LLVM_FALLTHROUGH;
501  default:
502  return ArgType::Invalid();
503  }
504 
505  if (CS.isIntArg())
506  switch (LM.getKind()) {
508  // GNU extension.
509  return Ctx.LongLongTy;
512  return Ctx.IntTy;
514  return ArgType(Ctx.IntTy, "__int32");
516  return ArgType::AnyCharTy;
517  case LengthModifier::AsShort: return Ctx.ShortTy;
518  case LengthModifier::AsLong: return Ctx.LongTy;
521  return Ctx.LongLongTy;
523  return ArgType(Ctx.LongLongTy, "__int64");
525  return ArgType(Ctx.getIntMaxType(), "intmax_t");
527  return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
529  return Ctx.getTargetInfo().getTriple().isArch64Bit()
530  ? ArgType(Ctx.LongLongTy, "__int64")
531  : ArgType(Ctx.IntTy, "__int32");
533  return ArgType::makePtrdiffT(
534  ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
538  return ArgType::Invalid();
539  }
540 
541  if (CS.isUIntArg())
542  switch (LM.getKind()) {
544  // GNU extension.
545  return Ctx.UnsignedLongLongTy;
548  return Ctx.UnsignedIntTy;
550  return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
551  case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
552  case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
553  case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
556  return Ctx.UnsignedLongLongTy;
558  return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
560  return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
562  return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
564  return Ctx.getTargetInfo().getTriple().isArch64Bit()
565  ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
566  : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
568  return ArgType::makePtrdiffT(
569  ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
573  return ArgType::Invalid();
574  }
575 
576  if (CS.isDoubleArg()) {
577  if (!VectorNumElts.isInvalid()) {
578  switch (LM.getKind()) {
580  return Ctx.HalfTy;
582  return Ctx.FloatTy;
584  default:
585  return Ctx.DoubleTy;
586  }
587  }
588 
589  if (LM.getKind() == LengthModifier::AsLongDouble)
590  return Ctx.LongDoubleTy;
591  return Ctx.DoubleTy;
592  }
593 
594  if (CS.getKind() == ConversionSpecifier::nArg) {
595  switch (LM.getKind()) {
597  return ArgType::PtrTo(Ctx.IntTy);
599  return ArgType::PtrTo(Ctx.SignedCharTy);
601  return ArgType::PtrTo(Ctx.ShortTy);
603  return ArgType::PtrTo(Ctx.LongTy);
606  return ArgType::PtrTo(Ctx.LongLongTy);
608  return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
610  return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
612  return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
614  return ArgType(); // FIXME: Is this a known extension?
621  return ArgType::Invalid();
623  llvm_unreachable("only used for OpenCL which doesn not handle nArg");
624  }
625  }
626 
627  switch (CS.getKind()) {
629  if (LM.getKind() == LengthModifier::AsWideChar) {
630  if (IsObjCLiteral)
632  "const unichar *");
633  return ArgType(ArgType::WCStrTy, "wchar_t *");
634  }
635  if (LM.getKind() == LengthModifier::AsWide)
636  return ArgType(ArgType::WCStrTy, "wchar_t *");
637  return ArgType::CStrTy;
639  if (IsObjCLiteral)
641  "const unichar *");
642  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
643  LM.getKind() == LengthModifier::AsShort)
644  return ArgType::CStrTy;
645  return ArgType(ArgType::WCStrTy, "wchar_t *");
647  if (IsObjCLiteral)
648  return ArgType(Ctx.UnsignedShortTy, "unichar");
649  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
650  LM.getKind() == LengthModifier::AsShort)
651  return Ctx.IntTy;
652  return ArgType(Ctx.WideCharTy, "wchar_t");
655  return ArgType::CPointerTy;
657  return ArgType::ObjCPointerTy;
658  default:
659  break;
660  }
661 
662  // FIXME: Handle other cases.
663  return ArgType();
664 }
665 
666 
667 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
668  bool IsObjCLiteral) const {
669  const PrintfConversionSpecifier &CS = getConversionSpecifier();
670 
671  if (!CS.consumesDataArgument())
672  return ArgType::Invalid();
673 
674  ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
675  if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
676  return ScalarTy;
677 
678  return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
679 }
680 
681 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
682  ASTContext &Ctx, bool IsObjCLiteral) {
683  // %n is different from other conversion specifiers; don't try to fix it.
684  if (CS.getKind() == ConversionSpecifier::nArg)
685  return false;
686 
687  // Handle Objective-C objects first. Note that while the '%@' specifier will
688  // not warn for structure pointer or void pointer arguments (because that's
689  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
690  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
691  if (QT->isObjCRetainableType()) {
692  if (!IsObjCLiteral)
693  return false;
694 
696 
697  // Disable irrelevant flags
698  HasThousandsGrouping = false;
699  HasPlusPrefix = false;
700  HasSpacePrefix = false;
701  HasAlternativeForm = false;
702  HasLeadingZeroes = false;
703  Precision.setHowSpecified(OptionalAmount::NotSpecified);
704  LM.setKind(LengthModifier::None);
705 
706  return true;
707  }
708 
709  // Handle strings next (char *, wchar_t *)
710  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
711  CS.setKind(ConversionSpecifier::sArg);
712 
713  // Disable irrelevant flags
714  HasAlternativeForm = 0;
715  HasLeadingZeroes = 0;
716 
717  // Set the long length modifier for wide characters
718  if (QT->getPointeeType()->isWideCharType())
719  LM.setKind(LengthModifier::AsWideChar);
720  else
721  LM.setKind(LengthModifier::None);
722 
723  return true;
724  }
725 
726  // If it's an enum, get its underlying type.
727  if (const EnumType *ETy = QT->getAs<EnumType>())
728  QT = ETy->getDecl()->getIntegerType();
729 
730  const BuiltinType *BT = QT->getAs<BuiltinType>();
731  if (!BT) {
732  const VectorType *VT = QT->getAs<VectorType>();
733  if (VT) {
734  QT = VT->getElementType();
735  BT = QT->getAs<BuiltinType>();
736  VectorNumElts = OptionalAmount(VT->getNumElements());
737  }
738  }
739 
740  // We can only work with builtin types.
741  if (!BT)
742  return false;
743 
744  // Set length modifier
745  switch (BT->getKind()) {
746  case BuiltinType::Bool:
747  case BuiltinType::WChar_U:
748  case BuiltinType::WChar_S:
749  case BuiltinType::Char8: // FIXME: Treat like 'char'?
750  case BuiltinType::Char16:
751  case BuiltinType::Char32:
752  case BuiltinType::UInt128:
753  case BuiltinType::Int128:
754  case BuiltinType::Half:
755  case BuiltinType::BFloat16:
756  case BuiltinType::Float16:
757  case BuiltinType::Float128:
758  case BuiltinType::ShortAccum:
759  case BuiltinType::Accum:
760  case BuiltinType::LongAccum:
761  case BuiltinType::UShortAccum:
762  case BuiltinType::UAccum:
763  case BuiltinType::ULongAccum:
764  case BuiltinType::ShortFract:
765  case BuiltinType::Fract:
766  case BuiltinType::LongFract:
767  case BuiltinType::UShortFract:
768  case BuiltinType::UFract:
769  case BuiltinType::ULongFract:
770  case BuiltinType::SatShortAccum:
771  case BuiltinType::SatAccum:
772  case BuiltinType::SatLongAccum:
773  case BuiltinType::SatUShortAccum:
774  case BuiltinType::SatUAccum:
775  case BuiltinType::SatULongAccum:
776  case BuiltinType::SatShortFract:
777  case BuiltinType::SatFract:
778  case BuiltinType::SatLongFract:
779  case BuiltinType::SatUShortFract:
780  case BuiltinType::SatUFract:
781  case BuiltinType::SatULongFract:
782  // Various types which are non-trivial to correct.
783  return false;
784 
785 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
786  case BuiltinType::Id:
787 #include "clang/Basic/OpenCLImageTypes.def"
788 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
789  case BuiltinType::Id:
790 #include "clang/Basic/OpenCLExtensionTypes.def"
791 #define SVE_TYPE(Name, Id, SingletonId) \
792  case BuiltinType::Id:
793 #include "clang/Basic/AArch64SVEACLETypes.def"
794 #define SIGNED_TYPE(Id, SingletonId)
795 #define UNSIGNED_TYPE(Id, SingletonId)
796 #define FLOATING_TYPE(Id, SingletonId)
797 #define BUILTIN_TYPE(Id, SingletonId) \
798  case BuiltinType::Id:
799 #include "clang/AST/BuiltinTypes.def"
800  // Misc other stuff which doesn't make sense here.
801  return false;
802 
803  case BuiltinType::UInt:
804  case BuiltinType::Int:
805  case BuiltinType::Float:
806  LM.setKind(VectorNumElts.isInvalid() ?
808  break;
809  case BuiltinType::Double:
810  LM.setKind(VectorNumElts.isInvalid() ?
812  break;
813  case BuiltinType::Char_U:
814  case BuiltinType::UChar:
815  case BuiltinType::Char_S:
816  case BuiltinType::SChar:
817  LM.setKind(LengthModifier::AsChar);
818  break;
819 
820  case BuiltinType::Short:
821  case BuiltinType::UShort:
822  LM.setKind(LengthModifier::AsShort);
823  break;
824 
825  case BuiltinType::Long:
826  case BuiltinType::ULong:
827  LM.setKind(LengthModifier::AsLong);
828  break;
829 
830  case BuiltinType::LongLong:
831  case BuiltinType::ULongLong:
832  LM.setKind(LengthModifier::AsLongLong);
833  break;
834 
835  case BuiltinType::LongDouble:
836  LM.setKind(LengthModifier::AsLongDouble);
837  break;
838  }
839 
840  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
841  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
842  namedTypeToLengthModifier(QT, LM);
843 
844  // If fixing the length modifier was enough, we might be done.
845  if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
846  // If we're going to offer a fix anyway, make sure the sign matches.
847  switch (CS.getKind()) {
850  if (QT->isSignedIntegerType())
852  break;
856  if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
858  break;
859  default:
860  // Other specifiers do not have signed/unsigned variants.
861  break;
862  }
863 
864  const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
865  if (ATR.isValid() && ATR.matchesType(Ctx, QT))
866  return true;
867  }
868 
869  // Set conversion specifier and disable any flags which do not apply to it.
870  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
871  if (!isa<TypedefType>(QT) && QT->isCharType()) {
872  CS.setKind(ConversionSpecifier::cArg);
873  LM.setKind(LengthModifier::None);
874  Precision.setHowSpecified(OptionalAmount::NotSpecified);
875  HasAlternativeForm = 0;
876  HasLeadingZeroes = 0;
877  HasPlusPrefix = 0;
878  }
879  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
880  else if (QT->isRealFloatingType()) {
881  CS.setKind(ConversionSpecifier::fArg);
882  }
883  else if (QT->isSignedIntegerType()) {
884  CS.setKind(ConversionSpecifier::dArg);
885  HasAlternativeForm = 0;
886  }
887  else if (QT->isUnsignedIntegerType()) {
888  CS.setKind(ConversionSpecifier::uArg);
889  HasAlternativeForm = 0;
890  HasPlusPrefix = 0;
891  } else {
892  llvm_unreachable("Unexpected type");
893  }
894 
895  return true;
896 }
897 
898 void PrintfSpecifier::toString(raw_ostream &os) const {
899  // Whilst some features have no defined order, we are using the order
900  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
901  os << "%";
902 
903  // Positional args
904  if (usesPositionalArg()) {
905  os << getPositionalArgIndex() << "$";
906  }
907 
908  // Conversion flags
909  if (IsLeftJustified) os << "-";
910  if (HasPlusPrefix) os << "+";
911  if (HasSpacePrefix) os << " ";
912  if (HasAlternativeForm) os << "#";
913  if (HasLeadingZeroes) os << "0";
914 
915  // Minimum field width
916  FieldWidth.toString(os);
917  // Precision
918  Precision.toString(os);
919 
920  // Vector modifier
921  if (!VectorNumElts.isInvalid())
922  os << 'v' << VectorNumElts.getConstantAmount();
923 
924  // Length modifier
925  os << LM.toString();
926  // Conversion specifier
927  os << CS.toString();
928 }
929 
930 bool PrintfSpecifier::hasValidPlusPrefix() const {
931  if (!HasPlusPrefix)
932  return true;
933 
934  // The plus prefix only makes sense for signed conversions
935  switch (CS.getKind()) {
949  return true;
950 
951  default:
952  return false;
953  }
954 }
955 
956 bool PrintfSpecifier::hasValidAlternativeForm() const {
957  if (!HasAlternativeForm)
958  return true;
959 
960  // Alternate form flag only valid with the oxXaAeEfFgG conversions
961  switch (CS.getKind()) {
976  return true;
977 
978  default:
979  return false;
980  }
981 }
982 
983 bool PrintfSpecifier::hasValidLeadingZeros() const {
984  if (!HasLeadingZeroes)
985  return true;
986 
987  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
988  switch (CS.getKind()) {
1008  return true;
1009 
1010  default:
1011  return false;
1012  }
1013 }
1014 
1015 bool PrintfSpecifier::hasValidSpacePrefix() const {
1016  if (!HasSpacePrefix)
1017  return true;
1018 
1019  // The space prefix only makes sense for signed conversions
1020  switch (CS.getKind()) {
1034  return true;
1035 
1036  default:
1037  return false;
1038  }
1039 }
1040 
1041 bool PrintfSpecifier::hasValidLeftJustified() const {
1042  if (!IsLeftJustified)
1043  return true;
1044 
1045  // The left justified flag is valid for all conversions except n
1046  switch (CS.getKind()) {
1048  return false;
1049 
1050  default:
1051  return true;
1052  }
1053 }
1054 
1055 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
1056  if (!HasThousandsGrouping)
1057  return true;
1058 
1059  switch (CS.getKind()) {
1069  return true;
1070  default:
1071  return false;
1072  }
1073 }
1074 
1075 bool PrintfSpecifier::hasValidPrecision() const {
1076  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
1077  return true;
1078 
1079  // Precision is only valid with the diouxXaAeEfFgGsP conversions
1080  switch (CS.getKind()) {
1102  return true;
1103 
1104  default:
1105  return false;
1106  }
1107 }
1108 bool PrintfSpecifier::hasValidFieldWidth() const {
1109  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1110  return true;
1111 
1112  // The field width is valid for all conversions except n
1113  switch (CS.getKind()) {
1115  return false;
1116 
1117  default:
1118  return true;
1119  }
1120 }
QualType withConst() const
Retrieves a version of this type with const applied.
CanQualType LongLongTy
Definition: ASTContext.h:951
static ArgType makePtrdiffT(const ArgType &A)
Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t type.
Definition: FormatString.h:310
A (possibly-)qualified type.
Definition: Type.h:655
void setIsPublic(const char *position)
Definition: FormatString.h:552
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
Kind getKind() const
Definition: Type.h:2533
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:627
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1060
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2114
bool ParseVectorModifier(FormatStringHandler &H, FormatSpecifier &FS, const char *&Beg, const char *E, const LangOptions &LO)
virtual void HandleInvalidObjCModifierFlag(const char *startFlag, unsigned flagLen)
Definition: FormatString.h:712
static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS, const char *FlagBeg, const char *E, bool Warn)
static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, const char *Start, const char *&Beg, const char *E, unsigned *argIndex)
bool ParseArgPosition(FormatStringHandler &H, FormatSpecifier &CS, const char *Start, const char *&Beg, const char *E)
CanQualType LongTy
Definition: ASTContext.h:951
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:647
void setHasLeadingZeros(const char *position)
Definition: FormatString.h:545
CanQualType WideCharTy
Definition: ASTContext.h:946
CanQualType HalfTy
Definition: ASTContext.h:966
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:2055
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:7153
virtual void HandleEmptyObjCModifierFlag(const char *startFlags, unsigned flagsLen)
Definition: FormatString.h:709
bool isWideCharType() const
Definition: Type.cpp:1960
void setPrecision(const OptionalAmount &Amt)
Definition: FormatString.h:564
static ArgType makeSizeT(const ArgType &A)
Create an ArgType which corresponds to the size_t/ssize_t type.
Definition: FormatString.h:302
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:174
Pieces specific to fprintf format strings.
Definition: FormatString.h:475
bool isCharType() const
Definition: Type.cpp:1951
void setHasSpacePrefix(const char *position)
Definition: FormatString.h:539
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:54
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
void setConversionSpecifier(const PrintfConversionSpecifier &cs)
Definition: FormatString.h:527
virtual bool HandleInvalidPrintfConversionSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:720
MatchKind matchesType(ASTContext &C, QualType argTy) const
Represents the length modifier in a format string in scanf/printf.
Definition: FormatString.h:64
CanQualType LongDoubleTy
Definition: ASTContext.h:954
void setIsLeftJustified(const char *position)
Definition: FormatString.h:533
virtual void handleInvalidMaskType(StringRef MaskType)
Handle mask types whose sizes are not between one and eight bytes.
Definition: FormatString.h:734
CanQualType UnsignedCharTy
Definition: ASTContext.h:952
static ArgType PtrTo(const ArgType &A)
Create an ArgType which corresponds to the type pointer to A.
Definition: FormatString.h:294
OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, unsigned &argIndex)
ArgType makeVectorType(ASTContext &C, unsigned NumElts) const
Exposes information about the current target.
Definition: TargetInfo.h:179
SourceLocation End
bool isObjCRetainableType() const
Definition: Type.cpp:4196
SourceLocation Begin
CanQualType ShortTy
Definition: ASTContext.h:951
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], or an enum decl which has a signed representation.
Definition: Type.cpp:2008
virtual void HandleNullChar(const char *nullCharacter)
Definition: FormatString.h:697
Represents a GCC generic vector type.
Definition: Type.h:3234
CanQualType SignedCharTy
Definition: ASTContext.h:951
CanQualType getUIntMaxType() const
Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in <stdint.h>.
bool ParseFormatStringHasSArg(const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target)
virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart, const char *flagsEnd, const char *conversionPosition)
Definition: FormatString.h:715
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums...
Definition: Type.h:4643
void setIsPrivate(const char *position)
Definition: FormatString.h:551
QualType getElementType() const
Definition: Type.h:3269
CanQualType FloatTy
Definition: ASTContext.h:954
CanQualType getSignedSizeType() const
Return the unique signed counterpart of the integer type corresponding to size_t. ...
void setHasThousandsGrouping(const char *position)
Definition: FormatString.h:530
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition: Type.cpp:1987
bool ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &CS, const char *Start, const char *&Beg, const char *E, unsigned *argIndex)
const PrintfConversionSpecifier & getConversionSpecifier() const
Definition: FormatString.h:560
virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:727
CanQualType UnsignedShortTy
Definition: ASTContext.h:952
Dataflow Directional Tag Classes.
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:953
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&#39;t go fur...
Common components of both fprintf and fscanf format strings.
Definition: FormatString.h:29
std::string toString(const til::SExpr *E)
void setHasObjCTechnicalTerm(const char *position)
Definition: FormatString.h:548
CanQualType UnsignedLongTy
Definition: ASTContext.h:952
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...
void setHasPlusPrefix(const char *position)
Definition: FormatString.h:536
virtual void HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:706
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
This class is used for builtin types like &#39;int&#39;.
Definition: Type.h:2504
Defines the clang::TargetInfo interface.
CanQualType IntTy
Definition: ASTContext.h:951
unsigned getNumElements() const
Definition: Type.h:3270
bool ParsePrintfString(FormatStringHandler &H, const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target, bool isFreeBSDKPrintf)
bool isPointerType() const
Definition: Type.h:6650
void setHasAlternativeForm(const char *position)
Definition: FormatString.h:542
void setIsSensitive(const char *position)
Definition: FormatString.h:553
clang::analyze_format_string::SpecifierResult< PrintfSpecifier > PrintfSpecifierResult
CanQualType getIntMaxType() const
Return the unique type for "intmax_t" (C99 7.18.1.5), defined in <stdint.h>.
CanQualType DoubleTy
Definition: ASTContext.h:954
__device__ __2f16 float c
static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, const char *&Beg, const char *E, unsigned &argIndex, const LangOptions &LO, const TargetInfo &Target, bool Warn, bool isFreeBSDKPrintf)
CanQualType UnsignedIntTy
Definition: ASTContext.h:952
OptionalAmount ParsePositionAmount(FormatStringHandler &H, const char *Start, const char *&Beg, const char *E, PositionContext p)
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
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.