clang  10.0.0svn
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 "clang/AST/FormatString.h"
15 #include "clang/AST/OSLog.h"
16 #include "FormatStringParsing.h"
17 #include "clang/Basic/TargetInfo.h"
18 
25 
26 using namespace clang;
27 
30 
31 //===----------------------------------------------------------------------===//
32 // Methods for parsing format strings.
33 //===----------------------------------------------------------------------===//
34 
36 
38  const char *Start, const char *&Beg, const char *E,
39  unsigned *argIndex) {
40  if (argIndex) {
41  FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
42  } else {
43  const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
45  if (Amt.isInvalid())
46  return true;
47  FS.setPrecision(Amt);
48  }
49  return false;
50 }
51 
53  const char *FlagBeg, const char *E, bool Warn) {
54  StringRef Flag(FlagBeg, E - FlagBeg);
55  // Currently there is only one flag.
56  if (Flag == "tt") {
57  FS.setHasObjCTechnicalTerm(FlagBeg);
58  return false;
59  }
60  // Handle either the case of no flag or an invalid flag.
61  if (Warn) {
62  if (Flag == "")
63  H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg);
64  else
65  H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg);
66  }
67  return true;
68 }
69 
71  const char *&Beg,
72  const char *E,
73  unsigned &argIndex,
74  const LangOptions &LO,
75  const TargetInfo &Target,
76  bool Warn,
77  bool isFreeBSDKPrintf) {
78 
79  using namespace clang::analyze_format_string;
80  using namespace clang::analyze_printf;
81 
82  const char *I = Beg;
83  const char *Start = nullptr;
84  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
85 
86  // Look for a '%' character that indicates the start of a format specifier.
87  for ( ; I != E ; ++I) {
88  char c = *I;
89  if (c == '\0') {
90  // Detect spurious null characters, which are likely errors.
91  H.HandleNullChar(I);
92  return true;
93  }
94  if (c == '%') {
95  Start = I++; // Record the start of the format specifier.
96  break;
97  }
98  }
99 
100  // No format specifier found?
101  if (!Start)
102  return false;
103 
104  if (I == E) {
105  // No more characters left?
106  if (Warn)
107  H.HandleIncompleteSpecifier(Start, E - Start);
108  return true;
109  }
110 
111  PrintfSpecifier FS;
112  if (ParseArgPosition(H, FS, Start, I, E))
113  return true;
114 
115  if (I == E) {
116  // No more characters left?
117  if (Warn)
118  H.HandleIncompleteSpecifier(Start, E - Start);
119  return true;
120  }
121 
122  if (*I == '{') {
123  ++I;
124  unsigned char PrivacyFlags = 0;
125  StringRef MatchedStr;
126 
127  do {
128  StringRef Str(I, E - I);
129  std::string Match = "^[[:space:]]*"
130  "(private|public|sensitive|mask\\.[^[:space:],}]*)"
131  "[[:space:]]*(,|})";
132  llvm::Regex R(Match);
134 
135  if (R.match(Str, &Matches)) {
136  MatchedStr = Matches[1];
137  I += Matches[0].size();
138 
139  // Set the privacy flag if the privacy annotation in the
140  // comma-delimited segment is at least as strict as the privacy
141  // annotations in previous comma-delimited segments.
142  if (MatchedStr.startswith("mask")) {
143  StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1);
144  unsigned Size = MaskType.size();
145  if (Warn && (Size == 0 || Size > 8))
146  H.handleInvalidMaskType(MaskType);
147  FS.setMaskType(MaskType);
148  } else if (MatchedStr.equals("sensitive"))
150  else if (PrivacyFlags !=
152  MatchedStr.equals("private"))
154  else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
156  } else {
157  size_t CommaOrBracePos =
158  Str.find_if([](char c) { return c == ',' || c == '}'; });
159 
160  if (CommaOrBracePos == StringRef::npos) {
161  // Neither a comma nor the closing brace was found.
162  if (Warn)
163  H.HandleIncompleteSpecifier(Start, E - Start);
164  return true;
165  }
166 
167  I += CommaOrBracePos + 1;
168  }
169  // Continue until the closing brace is found.
170  } while (*(I - 1) == ',');
171 
172  // Set the privacy flag.
173  switch (PrivacyFlags) {
174  case 0:
175  break;
177  FS.setIsPrivate(MatchedStr.data());
178  break;
180  FS.setIsPublic(MatchedStr.data());
181  break;
183  FS.setIsSensitive(MatchedStr.data());
184  break;
185  default:
186  llvm_unreachable("Unexpected privacy flag value");
187  }
188  }
189 
190  // Look for flags (if any).
191  bool hasMore = true;
192  for ( ; I != E; ++I) {
193  switch (*I) {
194  default: hasMore = false; break;
195  case '\'':
196  // FIXME: POSIX specific. Always accept?
198  break;
199  case '-': FS.setIsLeftJustified(I); break;
200  case '+': FS.setHasPlusPrefix(I); break;
201  case ' ': FS.setHasSpacePrefix(I); break;
202  case '#': FS.setHasAlternativeForm(I); break;
203  case '0': FS.setHasLeadingZeros(I); break;
204  }
205  if (!hasMore)
206  break;
207  }
208 
209  if (I == E) {
210  // No more characters left?
211  if (Warn)
212  H.HandleIncompleteSpecifier(Start, E - Start);
213  return true;
214  }
215 
216  // Look for the field width (if any).
217  if (ParseFieldWidth(H, FS, Start, I, E,
218  FS.usesPositionalArg() ? nullptr : &argIndex))
219  return true;
220 
221  if (I == E) {
222  // No more characters left?
223  if (Warn)
224  H.HandleIncompleteSpecifier(Start, E - Start);
225  return true;
226  }
227 
228  // Look for the precision (if any).
229  if (*I == '.') {
230  ++I;
231  if (I == E) {
232  if (Warn)
233  H.HandleIncompleteSpecifier(Start, E - Start);
234  return true;
235  }
236 
237  if (ParsePrecision(H, FS, Start, I, E,
238  FS.usesPositionalArg() ? nullptr : &argIndex))
239  return true;
240 
241  if (I == E) {
242  // No more characters left?
243  if (Warn)
244  H.HandleIncompleteSpecifier(Start, E - Start);
245  return true;
246  }
247  }
248 
249  if (ParseVectorModifier(H, FS, I, E, LO))
250  return true;
251 
252  // Look for the length modifier.
253  if (ParseLengthModifier(FS, I, E, LO) && I == E) {
254  // No more characters left?
255  if (Warn)
256  H.HandleIncompleteSpecifier(Start, E - Start);
257  return true;
258  }
259 
260  // Look for the Objective-C modifier flags, if any.
261  // We parse these here, even if they don't apply to
262  // the conversion specifier, and then emit an error
263  // later if the conversion specifier isn't '@'. This
264  // enables better recovery, and we don't know if
265  // these flags are applicable until later.
266  const char *ObjCModifierFlagsStart = nullptr,
267  *ObjCModifierFlagsEnd = nullptr;
268  if (*I == '[') {
269  ObjCModifierFlagsStart = I;
270  ++I;
271  auto flagStart = I;
272  for (;; ++I) {
273  ObjCModifierFlagsEnd = I;
274  if (I == E) {
275  if (Warn)
276  H.HandleIncompleteSpecifier(Start, E - Start);
277  return true;
278  }
279  // Did we find the closing ']'?
280  if (*I == ']') {
281  if (ParseObjCFlags(H, FS, flagStart, I, Warn))
282  return true;
283  ++I;
284  break;
285  }
286  // There are no separators defined yet for multiple
287  // Objective-C modifier flags. When those are
288  // defined, this is the place to check.
289  }
290  }
291 
292  if (*I == '\0') {
293  // Detect spurious null characters, which are likely errors.
294  H.HandleNullChar(I);
295  return true;
296  }
297 
298  // Finally, look for the conversion specifier.
299  const char *conversionPosition = I++;
301  switch (*conversionPosition) {
302  default:
303  break;
304  // C99: 7.19.6.1 (section 8).
305  case '%': k = ConversionSpecifier::PercentArg; break;
306  case 'A': k = ConversionSpecifier::AArg; break;
307  case 'E': k = ConversionSpecifier::EArg; break;
308  case 'F': k = ConversionSpecifier::FArg; break;
309  case 'G': k = ConversionSpecifier::GArg; break;
310  case 'X': k = ConversionSpecifier::XArg; break;
311  case 'a': k = ConversionSpecifier::aArg; break;
312  case 'c': k = ConversionSpecifier::cArg; break;
313  case 'd': k = ConversionSpecifier::dArg; break;
314  case 'e': k = ConversionSpecifier::eArg; break;
315  case 'f': k = ConversionSpecifier::fArg; break;
316  case 'g': k = ConversionSpecifier::gArg; break;
317  case 'i': k = ConversionSpecifier::iArg; break;
318  case 'n':
319  // Not handled, but reserved in OpenCL.
320  if (!LO.OpenCL)
322  break;
323  case 'o': k = ConversionSpecifier::oArg; break;
324  case 'p': k = ConversionSpecifier::pArg; break;
325  case 's': k = ConversionSpecifier::sArg; break;
326  case 'u': k = ConversionSpecifier::uArg; break;
327  case 'x': k = ConversionSpecifier::xArg; break;
328  // POSIX specific.
329  case 'C': k = ConversionSpecifier::CArg; break;
330  case 'S': k = ConversionSpecifier::SArg; break;
331  // Apple extension for os_log
332  case 'P':
334  break;
335  // Objective-C.
336  case '@': k = ConversionSpecifier::ObjCObjArg; break;
337  // Glibc specific.
338  case 'm': k = ConversionSpecifier::PrintErrno; break;
339  // FreeBSD kernel specific.
340  case 'b':
341  if (isFreeBSDKPrintf)
342  k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
343  break;
344  case 'r':
345  if (isFreeBSDKPrintf)
347  break;
348  case 'y':
349  if (isFreeBSDKPrintf)
351  break;
352  // Apple-specific.
353  case 'D':
354  if (isFreeBSDKPrintf)
355  k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
356  else if (Target.getTriple().isOSDarwin())
358  break;
359  case 'O':
360  if (Target.getTriple().isOSDarwin())
362  break;
363  case 'U':
364  if (Target.getTriple().isOSDarwin())
366  break;
367  // MS specific.
368  case 'Z':
369  if (Target.getTriple().isOSMSVCRT())
371  break;
372  }
373 
374  // Check to see if we used the Objective-C modifier flags with
375  // a conversion specifier other than '@'.
378  ObjCModifierFlagsStart) {
379  H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
380  ObjCModifierFlagsEnd + 1,
381  conversionPosition);
382  return true;
383  }
384 
385  PrintfConversionSpecifier CS(conversionPosition, k);
386  FS.setConversionSpecifier(CS);
387  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
388  FS.setArgIndex(argIndex++);
389  // FreeBSD kernel specific.
392  argIndex++;
393 
395  unsigned Len = I - Start;
396  if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
397  CS.setEndScanList(Start + Len);
398  FS.setConversionSpecifier(CS);
399  }
400  // Assume the conversion takes one argument.
401  return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
402  }
403  return PrintfSpecifierResult(Start, FS);
404 }
405 
407  const char *I,
408  const char *E,
409  const LangOptions &LO,
410  const TargetInfo &Target,
411  bool isFreeBSDKPrintf) {
412 
413  unsigned argIndex = 0;
414 
415  // Keep looking for a format specifier until we have exhausted the string.
416  while (I != E) {
417  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
418  LO, Target, true,
419  isFreeBSDKPrintf);
420  // Did a fail-stop error of any kind occur when parsing the specifier?
421  // If so, don't do any more processing.
422  if (FSR.shouldStop())
423  return true;
424  // Did we exhaust the string or encounter an error that
425  // we can recover from?
426  if (!FSR.hasValue())
427  continue;
428  // We have a format specifier. Pass it to the callback.
429  if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
430  I - FSR.getStart()))
431  return true;
432  }
433  assert(I == E && "Format string not exhausted");
434  return false;
435 }
436 
438  const char *E,
439  const LangOptions &LO,
440  const TargetInfo &Target) {
441 
442  unsigned argIndex = 0;
443 
444  // Keep looking for a %s format specifier until we have exhausted the string.
446  while (I != E) {
447  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
448  LO, Target, false,
449  false);
450  // Did a fail-stop error of any kind occur when parsing the specifier?
451  // If so, don't do any more processing.
452  if (FSR.shouldStop())
453  return false;
454  // Did we exhaust the string or encounter an error that
455  // we can recover from?
456  if (!FSR.hasValue())
457  continue;
458  const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
459  // Return true if this a %s format specifier.
460  if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
461  return true;
462  }
463  return false;
464 }
465 
467  const char *Begin, const char *End, const LangOptions &LO,
468  const TargetInfo &Target) {
469  unsigned ArgIndex = 0;
470  // Keep looking for a formatting specifier until we have exhausted the string.
472  while (Begin != End) {
473  const PrintfSpecifierResult &FSR =
474  ParsePrintfSpecifier(H, Begin, End, ArgIndex, LO, Target, false, false);
475  if (FSR.shouldStop())
476  break;
477  if (FSR.hasValue())
478  return true;
479  }
480  return false;
481 }
482 
483 //===----------------------------------------------------------------------===//
484 // Methods on PrintfSpecifier.
485 //===----------------------------------------------------------------------===//
486 
487 ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
488  bool IsObjCLiteral) const {
489  if (CS.getKind() == ConversionSpecifier::cArg)
490  switch (LM.getKind()) {
492  return Ctx.IntTy;
495  return ArgType(ArgType::WIntTy, "wint_t");
497  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
498  return Ctx.IntTy;
499  LLVM_FALLTHROUGH;
500  default:
501  return ArgType::Invalid();
502  }
503 
504  if (CS.isIntArg())
505  switch (LM.getKind()) {
507  // GNU extension.
508  return Ctx.LongLongTy;
511  return Ctx.IntTy;
513  return ArgType(Ctx.IntTy, "__int32");
515  return ArgType::AnyCharTy;
516  case LengthModifier::AsShort: return Ctx.ShortTy;
517  case LengthModifier::AsLong: return Ctx.LongTy;
520  return Ctx.LongLongTy;
522  return ArgType(Ctx.LongLongTy, "__int64");
524  return ArgType(Ctx.getIntMaxType(), "intmax_t");
526  return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
528  return Ctx.getTargetInfo().getTriple().isArch64Bit()
529  ? ArgType(Ctx.LongLongTy, "__int64")
530  : ArgType(Ctx.IntTy, "__int32");
532  return ArgType::makePtrdiffT(
533  ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
537  return ArgType::Invalid();
538  }
539 
540  if (CS.isUIntArg())
541  switch (LM.getKind()) {
543  // GNU extension.
544  return Ctx.UnsignedLongLongTy;
547  return Ctx.UnsignedIntTy;
549  return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
550  case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
551  case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
552  case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
555  return Ctx.UnsignedLongLongTy;
557  return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
559  return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
561  return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
563  return Ctx.getTargetInfo().getTriple().isArch64Bit()
564  ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
565  : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
567  return ArgType::makePtrdiffT(
568  ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
572  return ArgType::Invalid();
573  }
574 
575  if (CS.isDoubleArg()) {
576  if (!VectorNumElts.isInvalid()) {
577  switch (LM.getKind()) {
579  return Ctx.HalfTy;
581  return Ctx.FloatTy;
583  default:
584  return Ctx.DoubleTy;
585  }
586  }
587 
588  if (LM.getKind() == LengthModifier::AsLongDouble)
589  return Ctx.LongDoubleTy;
590  return Ctx.DoubleTy;
591  }
592 
593  if (CS.getKind() == ConversionSpecifier::nArg) {
594  switch (LM.getKind()) {
596  return ArgType::PtrTo(Ctx.IntTy);
598  return ArgType::PtrTo(Ctx.SignedCharTy);
600  return ArgType::PtrTo(Ctx.ShortTy);
602  return ArgType::PtrTo(Ctx.LongTy);
605  return ArgType::PtrTo(Ctx.LongLongTy);
607  return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
609  return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
611  return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
613  return ArgType(); // FIXME: Is this a known extension?
620  return ArgType::Invalid();
622  llvm_unreachable("only used for OpenCL which doesn not handle nArg");
623  }
624  }
625 
626  switch (CS.getKind()) {
628  if (LM.getKind() == LengthModifier::AsWideChar) {
629  if (IsObjCLiteral)
631  "const unichar *");
632  return ArgType(ArgType::WCStrTy, "wchar_t *");
633  }
634  if (LM.getKind() == LengthModifier::AsWide)
635  return ArgType(ArgType::WCStrTy, "wchar_t *");
636  return ArgType::CStrTy;
638  if (IsObjCLiteral)
640  "const unichar *");
641  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
642  LM.getKind() == LengthModifier::AsShort)
643  return ArgType::CStrTy;
644  return ArgType(ArgType::WCStrTy, "wchar_t *");
646  if (IsObjCLiteral)
647  return ArgType(Ctx.UnsignedShortTy, "unichar");
648  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
649  LM.getKind() == LengthModifier::AsShort)
650  return Ctx.IntTy;
651  return ArgType(Ctx.WideCharTy, "wchar_t");
654  return ArgType::CPointerTy;
656  return ArgType::ObjCPointerTy;
657  default:
658  break;
659  }
660 
661  // FIXME: Handle other cases.
662  return ArgType();
663 }
664 
665 
666 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
667  bool IsObjCLiteral) const {
668  const PrintfConversionSpecifier &CS = getConversionSpecifier();
669 
670  if (!CS.consumesDataArgument())
671  return ArgType::Invalid();
672 
673  ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
674  if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
675  return ScalarTy;
676 
677  return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
678 }
679 
680 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
681  ASTContext &Ctx, bool IsObjCLiteral) {
682  // %n is different from other conversion specifiers; don't try to fix it.
683  if (CS.getKind() == ConversionSpecifier::nArg)
684  return false;
685 
686  // Handle Objective-C objects first. Note that while the '%@' specifier will
687  // not warn for structure pointer or void pointer arguments (because that's
688  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
689  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
690  if (QT->isObjCRetainableType()) {
691  if (!IsObjCLiteral)
692  return false;
693 
695 
696  // Disable irrelevant flags
697  HasThousandsGrouping = false;
698  HasPlusPrefix = false;
699  HasSpacePrefix = false;
700  HasAlternativeForm = false;
701  HasLeadingZeroes = false;
702  Precision.setHowSpecified(OptionalAmount::NotSpecified);
703  LM.setKind(LengthModifier::None);
704 
705  return true;
706  }
707 
708  // Handle strings next (char *, wchar_t *)
709  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
710  CS.setKind(ConversionSpecifier::sArg);
711 
712  // Disable irrelevant flags
713  HasAlternativeForm = 0;
714  HasLeadingZeroes = 0;
715 
716  // Set the long length modifier for wide characters
717  if (QT->getPointeeType()->isWideCharType())
718  LM.setKind(LengthModifier::AsWideChar);
719  else
720  LM.setKind(LengthModifier::None);
721 
722  return true;
723  }
724 
725  // If it's an enum, get its underlying type.
726  if (const EnumType *ETy = QT->getAs<EnumType>())
727  QT = ETy->getDecl()->getIntegerType();
728 
729  const BuiltinType *BT = QT->getAs<BuiltinType>();
730  if (!BT) {
731  const VectorType *VT = QT->getAs<VectorType>();
732  if (VT) {
733  QT = VT->getElementType();
734  BT = QT->getAs<BuiltinType>();
735  VectorNumElts = OptionalAmount(VT->getNumElements());
736  }
737  }
738 
739  // We can only work with builtin types.
740  if (!BT)
741  return false;
742 
743  // Set length modifier
744  switch (BT->getKind()) {
745  case BuiltinType::Bool:
746  case BuiltinType::WChar_U:
747  case BuiltinType::WChar_S:
748  case BuiltinType::Char8: // FIXME: Treat like 'char'?
749  case BuiltinType::Char16:
750  case BuiltinType::Char32:
751  case BuiltinType::UInt128:
752  case BuiltinType::Int128:
753  case BuiltinType::Half:
754  case BuiltinType::Float16:
755  case BuiltinType::Float128:
756  case BuiltinType::ShortAccum:
757  case BuiltinType::Accum:
758  case BuiltinType::LongAccum:
759  case BuiltinType::UShortAccum:
760  case BuiltinType::UAccum:
761  case BuiltinType::ULongAccum:
762  case BuiltinType::ShortFract:
763  case BuiltinType::Fract:
764  case BuiltinType::LongFract:
765  case BuiltinType::UShortFract:
766  case BuiltinType::UFract:
767  case BuiltinType::ULongFract:
768  case BuiltinType::SatShortAccum:
769  case BuiltinType::SatAccum:
770  case BuiltinType::SatLongAccum:
771  case BuiltinType::SatUShortAccum:
772  case BuiltinType::SatUAccum:
773  case BuiltinType::SatULongAccum:
774  case BuiltinType::SatShortFract:
775  case BuiltinType::SatFract:
776  case BuiltinType::SatLongFract:
777  case BuiltinType::SatUShortFract:
778  case BuiltinType::SatUFract:
779  case BuiltinType::SatULongFract:
780  // Various types which are non-trivial to correct.
781  return false;
782 
783 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
784  case BuiltinType::Id:
785 #include "clang/Basic/OpenCLImageTypes.def"
786 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
787  case BuiltinType::Id:
788 #include "clang/Basic/OpenCLExtensionTypes.def"
789 #define SVE_TYPE(Name, Id, SingletonId) \
790  case BuiltinType::Id:
791 #include "clang/Basic/AArch64SVEACLETypes.def"
792 #define SIGNED_TYPE(Id, SingletonId)
793 #define UNSIGNED_TYPE(Id, SingletonId)
794 #define FLOATING_TYPE(Id, SingletonId)
795 #define BUILTIN_TYPE(Id, SingletonId) \
796  case BuiltinType::Id:
797 #include "clang/AST/BuiltinTypes.def"
798  // Misc other stuff which doesn't make sense here.
799  return false;
800 
801  case BuiltinType::UInt:
802  case BuiltinType::Int:
803  case BuiltinType::Float:
804  LM.setKind(VectorNumElts.isInvalid() ?
806  break;
807  case BuiltinType::Double:
808  LM.setKind(VectorNumElts.isInvalid() ?
810  break;
811  case BuiltinType::Char_U:
812  case BuiltinType::UChar:
813  case BuiltinType::Char_S:
814  case BuiltinType::SChar:
815  LM.setKind(LengthModifier::AsChar);
816  break;
817 
818  case BuiltinType::Short:
819  case BuiltinType::UShort:
820  LM.setKind(LengthModifier::AsShort);
821  break;
822 
823  case BuiltinType::Long:
824  case BuiltinType::ULong:
825  LM.setKind(LengthModifier::AsLong);
826  break;
827 
828  case BuiltinType::LongLong:
829  case BuiltinType::ULongLong:
830  LM.setKind(LengthModifier::AsLongLong);
831  break;
832 
833  case BuiltinType::LongDouble:
834  LM.setKind(LengthModifier::AsLongDouble);
835  break;
836  }
837 
838  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
839  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
840  namedTypeToLengthModifier(QT, LM);
841 
842  // If fixing the length modifier was enough, we might be done.
843  if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
844  // If we're going to offer a fix anyway, make sure the sign matches.
845  switch (CS.getKind()) {
848  if (QT->isSignedIntegerType())
850  break;
854  if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
856  break;
857  default:
858  // Other specifiers do not have signed/unsigned variants.
859  break;
860  }
861 
862  const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
863  if (ATR.isValid() && ATR.matchesType(Ctx, QT))
864  return true;
865  }
866 
867  // Set conversion specifier and disable any flags which do not apply to it.
868  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
869  if (!isa<TypedefType>(QT) && QT->isCharType()) {
870  CS.setKind(ConversionSpecifier::cArg);
871  LM.setKind(LengthModifier::None);
872  Precision.setHowSpecified(OptionalAmount::NotSpecified);
873  HasAlternativeForm = 0;
874  HasLeadingZeroes = 0;
875  HasPlusPrefix = 0;
876  }
877  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
878  else if (QT->isRealFloatingType()) {
879  CS.setKind(ConversionSpecifier::fArg);
880  }
881  else if (QT->isSignedIntegerType()) {
882  CS.setKind(ConversionSpecifier::dArg);
883  HasAlternativeForm = 0;
884  }
885  else if (QT->isUnsignedIntegerType()) {
886  CS.setKind(ConversionSpecifier::uArg);
887  HasAlternativeForm = 0;
888  HasPlusPrefix = 0;
889  } else {
890  llvm_unreachable("Unexpected type");
891  }
892 
893  return true;
894 }
895 
896 void PrintfSpecifier::toString(raw_ostream &os) const {
897  // Whilst some features have no defined order, we are using the order
898  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
899  os << "%";
900 
901  // Positional args
902  if (usesPositionalArg()) {
903  os << getPositionalArgIndex() << "$";
904  }
905 
906  // Conversion flags
907  if (IsLeftJustified) os << "-";
908  if (HasPlusPrefix) os << "+";
909  if (HasSpacePrefix) os << " ";
910  if (HasAlternativeForm) os << "#";
911  if (HasLeadingZeroes) os << "0";
912 
913  // Minimum field width
914  FieldWidth.toString(os);
915  // Precision
916  Precision.toString(os);
917 
918  // Vector modifier
919  if (!VectorNumElts.isInvalid())
920  os << 'v' << VectorNumElts.getConstantAmount();
921 
922  // Length modifier
923  os << LM.toString();
924  // Conversion specifier
925  os << CS.toString();
926 }
927 
928 bool PrintfSpecifier::hasValidPlusPrefix() const {
929  if (!HasPlusPrefix)
930  return true;
931 
932  // The plus prefix only makes sense for signed conversions
933  switch (CS.getKind()) {
947  return true;
948 
949  default:
950  return false;
951  }
952 }
953 
954 bool PrintfSpecifier::hasValidAlternativeForm() const {
955  if (!HasAlternativeForm)
956  return true;
957 
958  // Alternate form flag only valid with the oxXaAeEfFgG conversions
959  switch (CS.getKind()) {
974  return true;
975 
976  default:
977  return false;
978  }
979 }
980 
981 bool PrintfSpecifier::hasValidLeadingZeros() const {
982  if (!HasLeadingZeroes)
983  return true;
984 
985  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
986  switch (CS.getKind()) {
1006  return true;
1007 
1008  default:
1009  return false;
1010  }
1011 }
1012 
1013 bool PrintfSpecifier::hasValidSpacePrefix() const {
1014  if (!HasSpacePrefix)
1015  return true;
1016 
1017  // The space prefix only makes sense for signed conversions
1018  switch (CS.getKind()) {
1032  return true;
1033 
1034  default:
1035  return false;
1036  }
1037 }
1038 
1039 bool PrintfSpecifier::hasValidLeftJustified() const {
1040  if (!IsLeftJustified)
1041  return true;
1042 
1043  // The left justified flag is valid for all conversions except n
1044  switch (CS.getKind()) {
1046  return false;
1047 
1048  default:
1049  return true;
1050  }
1051 }
1052 
1053 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
1054  if (!HasThousandsGrouping)
1055  return true;
1056 
1057  switch (CS.getKind()) {
1067  return true;
1068  default:
1069  return false;
1070  }
1071 }
1072 
1073 bool PrintfSpecifier::hasValidPrecision() const {
1074  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
1075  return true;
1076 
1077  // Precision is only valid with the diouxXaAeEfFgGsP conversions
1078  switch (CS.getKind()) {
1100  return true;
1101 
1102  default:
1103  return false;
1104  }
1105 }
1106 bool PrintfSpecifier::hasValidFieldWidth() const {
1107  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1108  return true;
1109 
1110  // The field width is valid for all conversions except n
1111  switch (CS.getKind()) {
1113  return false;
1114 
1115  default:
1116  return true;
1117  }
1118 }
QualType withConst() const
Retrieves a version of this type with const applied.
CanQualType LongLongTy
Definition: ASTContext.h:1024
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:643
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:2466
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:557
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:991
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2024
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:1024
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:706
void setHasLeadingZeros(const char *position)
Definition: FormatString.h:545
CanQualType WideCharTy
Definition: ASTContext.h:1019
CanQualType HalfTy
Definition: ASTContext.h:1039
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:1971
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6858
virtual void HandleEmptyObjCModifierFlag(const char *startFlags, unsigned flagsLen)
Definition: FormatString.h:709
bool isWideCharType() const
Definition: Type.cpp:1883
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:160
Pieces specific to fprintf format strings.
Definition: FormatString.h:475
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
bool isCharType() const
Definition: Type.cpp:1874
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:49
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:1027
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:1025
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:163
SourceLocation End
bool isObjCRetainableType() const
Definition: Type.cpp:4057
SourceLocation Begin
CanQualType ShortTy
Definition: ASTContext.h:1024
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:1931
virtual void HandleNullChar(const char *nullCharacter)
Definition: FormatString.h:697
Represents a GCC generic vector type.
Definition: Type.h:3206
CanQualType SignedCharTy
Definition: ASTContext.h:1024
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:4470
void setIsPrivate(const char *position)
Definition: FormatString.h:551
QualType getElementType() const
Definition: Type.h:3241
CanQualType FloatTy
Definition: ASTContext.h:1027
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:1910
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:1025
Dataflow Directional Tag Classes.
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:1026
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
void setHasObjCTechnicalTerm(const char *position)
Definition: FormatString.h:548
CanQualType UnsignedLongTy
Definition: ASTContext.h:1025
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:2436
Defines the clang::TargetInfo interface.
CanQualType IntTy
Definition: ASTContext.h:1024
unsigned getNumElements() const
Definition: Type.h:3242
bool ParsePrintfString(FormatStringHandler &H, const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target, bool isFreeBSDKPrintf)
bool isPointerType() const
Definition: Type.h:6391
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:1027
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:1025
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.