clang  8.0.0svn
PrintfFormatString.cpp
Go to the documentation of this file.
1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Handling of format string in printf and friends. The structure of format
11 // strings for fprintf() are described in C99 7.19.6.1.
12 //
13 //===----------------------------------------------------------------------===//
14 
17 #include "FormatStringParsing.h"
18 #include "clang/Basic/TargetInfo.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 = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})";
131  llvm::Regex R(Match);
133 
134  if (R.match(Str, &Matches)) {
135  MatchedStr = Matches[1];
136  I += Matches[0].size();
137 
138  // Set the privacy flag if the privacy annotation in the
139  // comma-delimited segment is at least as strict as the privacy
140  // annotations in previous comma-delimited segments.
141  if (MatchedStr.equals("private"))
143  else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
145  } else {
146  size_t CommaOrBracePos =
147  Str.find_if([](char c) { return c == ',' || c == '}'; });
148 
149  if (CommaOrBracePos == StringRef::npos) {
150  // Neither a comma nor the closing brace was found.
151  if (Warn)
152  H.HandleIncompleteSpecifier(Start, E - Start);
153  return true;
154  }
155 
156  I += CommaOrBracePos + 1;
157  }
158  // Continue until the closing brace is found.
159  } while (*(I - 1) == ',');
160 
161  // Set the privacy flag.
162  switch (PrivacyFlags) {
163  case 0:
164  break;
166  FS.setIsPrivate(MatchedStr.data());
167  break;
169  FS.setIsPublic(MatchedStr.data());
170  break;
171  default:
172  llvm_unreachable("Unexpected privacy flag value");
173  }
174  }
175 
176  // Look for flags (if any).
177  bool hasMore = true;
178  for ( ; I != E; ++I) {
179  switch (*I) {
180  default: hasMore = false; break;
181  case '\'':
182  // FIXME: POSIX specific. Always accept?
184  break;
185  case '-': FS.setIsLeftJustified(I); break;
186  case '+': FS.setHasPlusPrefix(I); break;
187  case ' ': FS.setHasSpacePrefix(I); break;
188  case '#': FS.setHasAlternativeForm(I); break;
189  case '0': FS.setHasLeadingZeros(I); break;
190  }
191  if (!hasMore)
192  break;
193  }
194 
195  if (I == E) {
196  // No more characters left?
197  if (Warn)
198  H.HandleIncompleteSpecifier(Start, E - Start);
199  return true;
200  }
201 
202  // Look for the field width (if any).
203  if (ParseFieldWidth(H, FS, Start, I, E,
204  FS.usesPositionalArg() ? nullptr : &argIndex))
205  return true;
206 
207  if (I == E) {
208  // No more characters left?
209  if (Warn)
210  H.HandleIncompleteSpecifier(Start, E - Start);
211  return true;
212  }
213 
214  // Look for the precision (if any).
215  if (*I == '.') {
216  ++I;
217  if (I == E) {
218  if (Warn)
219  H.HandleIncompleteSpecifier(Start, E - Start);
220  return true;
221  }
222 
223  if (ParsePrecision(H, FS, Start, I, E,
224  FS.usesPositionalArg() ? nullptr : &argIndex))
225  return true;
226 
227  if (I == E) {
228  // No more characters left?
229  if (Warn)
230  H.HandleIncompleteSpecifier(Start, E - Start);
231  return true;
232  }
233  }
234 
235  // Look for the length modifier.
236  if (ParseLengthModifier(FS, I, E, LO) && I == E) {
237  // No more characters left?
238  if (Warn)
239  H.HandleIncompleteSpecifier(Start, E - Start);
240  return true;
241  }
242 
243  // Look for the Objective-C modifier flags, if any.
244  // We parse these here, even if they don't apply to
245  // the conversion specifier, and then emit an error
246  // later if the conversion specifier isn't '@'. This
247  // enables better recovery, and we don't know if
248  // these flags are applicable until later.
249  const char *ObjCModifierFlagsStart = nullptr,
250  *ObjCModifierFlagsEnd = nullptr;
251  if (*I == '[') {
252  ObjCModifierFlagsStart = I;
253  ++I;
254  auto flagStart = I;
255  for (;; ++I) {
256  ObjCModifierFlagsEnd = I;
257  if (I == E) {
258  if (Warn)
259  H.HandleIncompleteSpecifier(Start, E - Start);
260  return true;
261  }
262  // Did we find the closing ']'?
263  if (*I == ']') {
264  if (ParseObjCFlags(H, FS, flagStart, I, Warn))
265  return true;
266  ++I;
267  break;
268  }
269  // There are no separators defined yet for multiple
270  // Objective-C modifier flags. When those are
271  // defined, this is the place to check.
272  }
273  }
274 
275  if (*I == '\0') {
276  // Detect spurious null characters, which are likely errors.
277  H.HandleNullChar(I);
278  return true;
279  }
280 
281  // Finally, look for the conversion specifier.
282  const char *conversionPosition = I++;
284  switch (*conversionPosition) {
285  default:
286  break;
287  // C99: 7.19.6.1 (section 8).
288  case '%': k = ConversionSpecifier::PercentArg; break;
289  case 'A': k = ConversionSpecifier::AArg; break;
290  case 'E': k = ConversionSpecifier::EArg; break;
291  case 'F': k = ConversionSpecifier::FArg; break;
292  case 'G': k = ConversionSpecifier::GArg; break;
293  case 'X': k = ConversionSpecifier::XArg; break;
294  case 'a': k = ConversionSpecifier::aArg; break;
295  case 'c': k = ConversionSpecifier::cArg; break;
296  case 'd': k = ConversionSpecifier::dArg; break;
297  case 'e': k = ConversionSpecifier::eArg; break;
298  case 'f': k = ConversionSpecifier::fArg; break;
299  case 'g': k = ConversionSpecifier::gArg; break;
300  case 'i': k = ConversionSpecifier::iArg; break;
301  case 'n': k = ConversionSpecifier::nArg; break;
302  case 'o': k = ConversionSpecifier::oArg; break;
303  case 'p': k = ConversionSpecifier::pArg; break;
304  case 's': k = ConversionSpecifier::sArg; break;
305  case 'u': k = ConversionSpecifier::uArg; break;
306  case 'x': k = ConversionSpecifier::xArg; break;
307  // POSIX specific.
308  case 'C': k = ConversionSpecifier::CArg; break;
309  case 'S': k = ConversionSpecifier::SArg; break;
310  // Apple extension for os_log
311  case 'P':
313  break;
314  // Objective-C.
315  case '@': k = ConversionSpecifier::ObjCObjArg; break;
316  // Glibc specific.
317  case 'm': k = ConversionSpecifier::PrintErrno; break;
318  // FreeBSD kernel specific.
319  case 'b':
320  if (isFreeBSDKPrintf)
321  k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
322  break;
323  case 'r':
324  if (isFreeBSDKPrintf)
326  break;
327  case 'y':
328  if (isFreeBSDKPrintf)
330  break;
331  // Apple-specific.
332  case 'D':
333  if (isFreeBSDKPrintf)
334  k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
335  else if (Target.getTriple().isOSDarwin())
337  break;
338  case 'O':
339  if (Target.getTriple().isOSDarwin())
341  break;
342  case 'U':
343  if (Target.getTriple().isOSDarwin())
345  break;
346  // MS specific.
347  case 'Z':
348  if (Target.getTriple().isOSMSVCRT())
350  }
351 
352  // Check to see if we used the Objective-C modifier flags with
353  // a conversion specifier other than '@'.
356  ObjCModifierFlagsStart) {
357  H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
358  ObjCModifierFlagsEnd + 1,
359  conversionPosition);
360  return true;
361  }
362 
363  PrintfConversionSpecifier CS(conversionPosition, k);
364  FS.setConversionSpecifier(CS);
365  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
366  FS.setArgIndex(argIndex++);
367  // FreeBSD kernel specific.
370  argIndex++;
371 
373  unsigned Len = I - Start;
374  if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
375  CS.setEndScanList(Start + Len);
376  FS.setConversionSpecifier(CS);
377  }
378  // Assume the conversion takes one argument.
379  return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
380  }
381  return PrintfSpecifierResult(Start, FS);
382 }
383 
385  const char *I,
386  const char *E,
387  const LangOptions &LO,
388  const TargetInfo &Target,
389  bool isFreeBSDKPrintf) {
390 
391  unsigned argIndex = 0;
392 
393  // Keep looking for a format specifier until we have exhausted the string.
394  while (I != E) {
395  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
396  LO, Target, true,
397  isFreeBSDKPrintf);
398  // Did a fail-stop error of any kind occur when parsing the specifier?
399  // If so, don't do any more processing.
400  if (FSR.shouldStop())
401  return true;
402  // Did we exhaust the string or encounter an error that
403  // we can recover from?
404  if (!FSR.hasValue())
405  continue;
406  // We have a format specifier. Pass it to the callback.
407  if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
408  I - FSR.getStart()))
409  return true;
410  }
411  assert(I == E && "Format string not exhausted");
412  return false;
413 }
414 
416  const char *E,
417  const LangOptions &LO,
418  const TargetInfo &Target) {
419 
420  unsigned argIndex = 0;
421 
422  // Keep looking for a %s format specifier until we have exhausted the string.
424  while (I != E) {
425  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
426  LO, Target, false,
427  false);
428  // Did a fail-stop error of any kind occur when parsing the specifier?
429  // If so, don't do any more processing.
430  if (FSR.shouldStop())
431  return false;
432  // Did we exhaust the string or encounter an error that
433  // we can recover from?
434  if (!FSR.hasValue())
435  continue;
436  const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
437  // Return true if this a %s format specifier.
438  if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
439  return true;
440  }
441  return false;
442 }
443 
444 //===----------------------------------------------------------------------===//
445 // Methods on PrintfSpecifier.
446 //===----------------------------------------------------------------------===//
447 
448 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
449  bool IsObjCLiteral) const {
450  const PrintfConversionSpecifier &CS = getConversionSpecifier();
451 
452  if (!CS.consumesDataArgument())
453  return ArgType::Invalid();
454 
456  switch (LM.getKind()) {
458  return Ctx.IntTy;
461  return ArgType(ArgType::WIntTy, "wint_t");
463  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
464  return Ctx.IntTy;
465  LLVM_FALLTHROUGH;
466  default:
467  return ArgType::Invalid();
468  }
469 
470  if (CS.isIntArg())
471  switch (LM.getKind()) {
473  // GNU extension.
474  return Ctx.LongLongTy;
476  return Ctx.IntTy;
478  return ArgType(Ctx.IntTy, "__int32");
480  case LengthModifier::AsShort: return Ctx.ShortTy;
481  case LengthModifier::AsLong: return Ctx.LongTy;
484  return Ctx.LongLongTy;
486  return ArgType(Ctx.LongLongTy, "__int64");
488  return ArgType(Ctx.getIntMaxType(), "intmax_t");
490  return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
492  return Ctx.getTargetInfo().getTriple().isArch64Bit()
493  ? ArgType(Ctx.LongLongTy, "__int64")
494  : ArgType(Ctx.IntTy, "__int32");
496  return ArgType::makePtrdiffT(
497  ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
501  return ArgType::Invalid();
502  }
503 
504  if (CS.isUIntArg())
505  switch (LM.getKind()) {
507  // GNU extension.
508  return Ctx.UnsignedLongLongTy;
510  return Ctx.UnsignedIntTy;
512  return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
513  case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
514  case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
515  case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
518  return Ctx.UnsignedLongLongTy;
520  return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
522  return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
524  return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
526  return Ctx.getTargetInfo().getTriple().isArch64Bit()
527  ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
528  : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
530  return ArgType::makePtrdiffT(
531  ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
535  return ArgType::Invalid();
536  }
537 
538  if (CS.isDoubleArg()) {
539  if (LM.getKind() == LengthModifier::AsLongDouble)
540  return Ctx.LongDoubleTy;
541  return Ctx.DoubleTy;
542  }
543 
544  if (CS.getKind() == ConversionSpecifier::nArg) {
545  switch (LM.getKind()) {
547  return ArgType::PtrTo(Ctx.IntTy);
549  return ArgType::PtrTo(Ctx.SignedCharTy);
551  return ArgType::PtrTo(Ctx.ShortTy);
553  return ArgType::PtrTo(Ctx.LongTy);
556  return ArgType::PtrTo(Ctx.LongLongTy);
558  return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
560  return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
562  return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
564  return ArgType(); // FIXME: Is this a known extension?
571  return ArgType::Invalid();
572  }
573  }
574 
575  switch (CS.getKind()) {
577  if (LM.getKind() == LengthModifier::AsWideChar) {
578  if (IsObjCLiteral)
580  "const unichar *");
581  return ArgType(ArgType::WCStrTy, "wchar_t *");
582  }
583  if (LM.getKind() == LengthModifier::AsWide)
584  return ArgType(ArgType::WCStrTy, "wchar_t *");
585  return ArgType::CStrTy;
587  if (IsObjCLiteral)
589  "const unichar *");
590  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
591  LM.getKind() == LengthModifier::AsShort)
592  return ArgType::CStrTy;
593  return ArgType(ArgType::WCStrTy, "wchar_t *");
595  if (IsObjCLiteral)
596  return ArgType(Ctx.UnsignedShortTy, "unichar");
597  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
598  LM.getKind() == LengthModifier::AsShort)
599  return Ctx.IntTy;
600  return ArgType(Ctx.WideCharTy, "wchar_t");
603  return ArgType::CPointerTy;
605  return ArgType::ObjCPointerTy;
606  default:
607  break;
608  }
609 
610  // FIXME: Handle other cases.
611  return ArgType();
612 }
613 
614 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
615  ASTContext &Ctx, bool IsObjCLiteral) {
616  // %n is different from other conversion specifiers; don't try to fix it.
617  if (CS.getKind() == ConversionSpecifier::nArg)
618  return false;
619 
620  // Handle Objective-C objects first. Note that while the '%@' specifier will
621  // not warn for structure pointer or void pointer arguments (because that's
622  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
623  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
624  if (QT->isObjCRetainableType()) {
625  if (!IsObjCLiteral)
626  return false;
627 
629 
630  // Disable irrelevant flags
631  HasThousandsGrouping = false;
632  HasPlusPrefix = false;
633  HasSpacePrefix = false;
634  HasAlternativeForm = false;
635  HasLeadingZeroes = false;
636  Precision.setHowSpecified(OptionalAmount::NotSpecified);
637  LM.setKind(LengthModifier::None);
638 
639  return true;
640  }
641 
642  // Handle strings next (char *, wchar_t *)
643  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
644  CS.setKind(ConversionSpecifier::sArg);
645 
646  // Disable irrelevant flags
647  HasAlternativeForm = 0;
648  HasLeadingZeroes = 0;
649 
650  // Set the long length modifier for wide characters
651  if (QT->getPointeeType()->isWideCharType())
652  LM.setKind(LengthModifier::AsWideChar);
653  else
654  LM.setKind(LengthModifier::None);
655 
656  return true;
657  }
658 
659  // If it's an enum, get its underlying type.
660  if (const EnumType *ETy = QT->getAs<EnumType>())
661  QT = ETy->getDecl()->getIntegerType();
662 
663  // We can only work with builtin types.
664  const BuiltinType *BT = QT->getAs<BuiltinType>();
665  if (!BT)
666  return false;
667 
668  // Set length modifier
669  switch (BT->getKind()) {
670  case BuiltinType::Bool:
671  case BuiltinType::WChar_U:
672  case BuiltinType::WChar_S:
673  case BuiltinType::Char8: // FIXME: Treat like 'char'?
674  case BuiltinType::Char16:
675  case BuiltinType::Char32:
676  case BuiltinType::UInt128:
677  case BuiltinType::Int128:
678  case BuiltinType::Half:
679  case BuiltinType::Float16:
680  case BuiltinType::Float128:
681  case BuiltinType::ShortAccum:
682  case BuiltinType::Accum:
683  case BuiltinType::LongAccum:
684  case BuiltinType::UShortAccum:
685  case BuiltinType::UAccum:
686  case BuiltinType::ULongAccum:
687  case BuiltinType::ShortFract:
688  case BuiltinType::Fract:
689  case BuiltinType::LongFract:
690  case BuiltinType::UShortFract:
691  case BuiltinType::UFract:
692  case BuiltinType::ULongFract:
693  case BuiltinType::SatShortAccum:
694  case BuiltinType::SatAccum:
695  case BuiltinType::SatLongAccum:
696  case BuiltinType::SatUShortAccum:
697  case BuiltinType::SatUAccum:
698  case BuiltinType::SatULongAccum:
699  case BuiltinType::SatShortFract:
700  case BuiltinType::SatFract:
701  case BuiltinType::SatLongFract:
702  case BuiltinType::SatUShortFract:
703  case BuiltinType::SatUFract:
704  case BuiltinType::SatULongFract:
705  // Various types which are non-trivial to correct.
706  return false;
707 
708 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
709  case BuiltinType::Id:
710 #include "clang/Basic/OpenCLImageTypes.def"
711 #define SIGNED_TYPE(Id, SingletonId)
712 #define UNSIGNED_TYPE(Id, SingletonId)
713 #define FLOATING_TYPE(Id, SingletonId)
714 #define BUILTIN_TYPE(Id, SingletonId) \
715  case BuiltinType::Id:
716 #include "clang/AST/BuiltinTypes.def"
717  // Misc other stuff which doesn't make sense here.
718  return false;
719 
720  case BuiltinType::UInt:
721  case BuiltinType::Int:
722  case BuiltinType::Float:
723  case BuiltinType::Double:
724  LM.setKind(LengthModifier::None);
725  break;
726 
727  case BuiltinType::Char_U:
728  case BuiltinType::UChar:
729  case BuiltinType::Char_S:
730  case BuiltinType::SChar:
731  LM.setKind(LengthModifier::AsChar);
732  break;
733 
734  case BuiltinType::Short:
735  case BuiltinType::UShort:
736  LM.setKind(LengthModifier::AsShort);
737  break;
738 
739  case BuiltinType::Long:
740  case BuiltinType::ULong:
741  LM.setKind(LengthModifier::AsLong);
742  break;
743 
744  case BuiltinType::LongLong:
745  case BuiltinType::ULongLong:
746  LM.setKind(LengthModifier::AsLongLong);
747  break;
748 
749  case BuiltinType::LongDouble:
750  LM.setKind(LengthModifier::AsLongDouble);
751  break;
752  }
753 
754  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
755  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
756  namedTypeToLengthModifier(QT, LM);
757 
758  // If fixing the length modifier was enough, we might be done.
759  if (hasValidLengthModifier(Ctx.getTargetInfo())) {
760  // If we're going to offer a fix anyway, make sure the sign matches.
761  switch (CS.getKind()) {
764  if (QT->isSignedIntegerType())
766  break;
770  if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
772  break;
773  default:
774  // Other specifiers do not have signed/unsigned variants.
775  break;
776  }
777 
778  const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
779  if (ATR.isValid() && ATR.matchesType(Ctx, QT))
780  return true;
781  }
782 
783  // Set conversion specifier and disable any flags which do not apply to it.
784  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
785  if (!isa<TypedefType>(QT) && QT->isCharType()) {
786  CS.setKind(ConversionSpecifier::cArg);
787  LM.setKind(LengthModifier::None);
788  Precision.setHowSpecified(OptionalAmount::NotSpecified);
789  HasAlternativeForm = 0;
790  HasLeadingZeroes = 0;
791  HasPlusPrefix = 0;
792  }
793  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
794  else if (QT->isRealFloatingType()) {
795  CS.setKind(ConversionSpecifier::fArg);
796  }
797  else if (QT->isSignedIntegerType()) {
798  CS.setKind(ConversionSpecifier::dArg);
799  HasAlternativeForm = 0;
800  }
801  else if (QT->isUnsignedIntegerType()) {
802  CS.setKind(ConversionSpecifier::uArg);
803  HasAlternativeForm = 0;
804  HasPlusPrefix = 0;
805  } else {
806  llvm_unreachable("Unexpected type");
807  }
808 
809  return true;
810 }
811 
812 void PrintfSpecifier::toString(raw_ostream &os) const {
813  // Whilst some features have no defined order, we are using the order
814  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
815  os << "%";
816 
817  // Positional args
818  if (usesPositionalArg()) {
819  os << getPositionalArgIndex() << "$";
820  }
821 
822  // Conversion flags
823  if (IsLeftJustified) os << "-";
824  if (HasPlusPrefix) os << "+";
825  if (HasSpacePrefix) os << " ";
826  if (HasAlternativeForm) os << "#";
827  if (HasLeadingZeroes) os << "0";
828 
829  // Minimum field width
830  FieldWidth.toString(os);
831  // Precision
832  Precision.toString(os);
833  // Length modifier
834  os << LM.toString();
835  // Conversion specifier
836  os << CS.toString();
837 }
838 
839 bool PrintfSpecifier::hasValidPlusPrefix() const {
840  if (!HasPlusPrefix)
841  return true;
842 
843  // The plus prefix only makes sense for signed conversions
844  switch (CS.getKind()) {
858  return true;
859 
860  default:
861  return false;
862  }
863 }
864 
865 bool PrintfSpecifier::hasValidAlternativeForm() const {
866  if (!HasAlternativeForm)
867  return true;
868 
869  // Alternate form flag only valid with the oxXaAeEfFgG conversions
870  switch (CS.getKind()) {
885  return true;
886 
887  default:
888  return false;
889  }
890 }
891 
892 bool PrintfSpecifier::hasValidLeadingZeros() const {
893  if (!HasLeadingZeroes)
894  return true;
895 
896  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
897  switch (CS.getKind()) {
917  return true;
918 
919  default:
920  return false;
921  }
922 }
923 
924 bool PrintfSpecifier::hasValidSpacePrefix() const {
925  if (!HasSpacePrefix)
926  return true;
927 
928  // The space prefix only makes sense for signed conversions
929  switch (CS.getKind()) {
943  return true;
944 
945  default:
946  return false;
947  }
948 }
949 
950 bool PrintfSpecifier::hasValidLeftJustified() const {
951  if (!IsLeftJustified)
952  return true;
953 
954  // The left justified flag is valid for all conversions except n
955  switch (CS.getKind()) {
957  return false;
958 
959  default:
960  return true;
961  }
962 }
963 
964 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
965  if (!HasThousandsGrouping)
966  return true;
967 
968  switch (CS.getKind()) {
978  return true;
979  default:
980  return false;
981  }
982 }
983 
984 bool PrintfSpecifier::hasValidPrecision() const {
985  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
986  return true;
987 
988  // Precision is only valid with the diouxXaAeEfFgGsP conversions
989  switch (CS.getKind()) {
1011  return true;
1012 
1013  default:
1014  return false;
1015  }
1016 }
1017 bool PrintfSpecifier::hasValidFieldWidth() const {
1018  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1019  return true;
1020 
1021  // The field width is valid for all conversions except n
1022  switch (CS.getKind()) {
1024  return false;
1025 
1026  default:
1027  return true;
1028  }
1029 }
QualType withConst() const
Retrieves a version of this type with const applied.
CanQualType LongLongTy
Definition: ASTContext.h:1032
static ArgType makePtrdiffT(const ArgType &A)
Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t type.
Definition: FormatString.h:296
A (possibly-)qualified type.
Definition: Type.h:641
void setIsPublic(const char *position)
Definition: FormatString.h:514
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
Kind getKind() const
Definition: Type.h:2378
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:497
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:949
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:1941
virtual void HandleInvalidObjCModifierFlag(const char *startFlag, unsigned flagLen)
Definition: FormatString.h:667
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:1032
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:698
void setHasLeadingZeros(const char *position)
Definition: FormatString.h:507
CanQualType WideCharTy
Definition: ASTContext.h:1027
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:1888
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6625
virtual void HandleEmptyObjCModifierFlag(const char *startFlags, unsigned flagsLen)
Definition: FormatString.h:664
bool isWideCharType() const
Definition: Type.cpp:1800
void setPrecision(const OptionalAmount &Amt)
Definition: FormatString.h:523
static ArgType makeSizeT(const ArgType &A)
Create an ArgType which corresponds to the size_t/ssize_t type.
Definition: FormatString.h:288
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:153
Pieces specific to fprintf format strings.
Definition: FormatString.h:443
bool isCharType() const
Definition: Type.cpp:1791
void setHasSpacePrefix(const char *position)
Definition: FormatString.h:501
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:50
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
void setConversionSpecifier(const PrintfConversionSpecifier &cs)
Definition: FormatString.h:489
virtual bool HandleInvalidPrintfConversionSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:675
MatchKind matchesType(ASTContext &C, QualType argTy) const
Represents the length modifier in a format string in scanf/printf.
Definition: FormatString.h:65
CanQualType LongDoubleTy
Definition: ASTContext.h:1035
void setIsLeftJustified(const char *position)
Definition: FormatString.h:495
CanQualType UnsignedCharTy
Definition: ASTContext.h:1033
static ArgType PtrTo(const ArgType &A)
Create an ArgType which corresponds to the type pointer to A.
Definition: FormatString.h:280
OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, unsigned &argIndex)
Exposes information about the current target.
Definition: TargetInfo.h:54
bool isObjCRetainableType() const
Definition: Type.cpp:3942
CanQualType ShortTy
Definition: ASTContext.h:1032
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:1848
virtual void HandleNullChar(const char *nullCharacter)
Definition: FormatString.h:652
CanQualType SignedCharTy
Definition: ASTContext.h:1032
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:670
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums...
Definition: Type.h:4265
void setIsPrivate(const char *position)
Definition: FormatString.h:513
CanQualType getSignedSizeType() const
Return the unique signed counterpart of the integer type corresponding to size_t. ...
void setHasThousandsGrouping(const char *position)
Definition: FormatString.h:492
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition: Type.cpp:1827
bool ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &CS, const char *Start, const char *&Beg, const char *E, unsigned *argIndex)
const PrintfConversionSpecifier & getConversionSpecifier() const
Definition: FormatString.h:519
virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:682
CanQualType UnsignedShortTy
Definition: ASTContext.h:1033
Dataflow Directional Tag Classes.
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:1034
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:30
std::string toString(const til::SExpr *E)
void setHasObjCTechnicalTerm(const char *position)
Definition: FormatString.h:510
CanQualType UnsignedLongTy
Definition: ASTContext.h:1033
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:498
virtual void HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:661
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:2354
Defines the clang::TargetInfo interface.
CanQualType IntTy
Definition: ASTContext.h:1032
bool ParsePrintfString(FormatStringHandler &H, const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target, bool isFreeBSDKPrintf)
bool isPointerType() const
Definition: Type.h:6212
void setHasAlternativeForm(const char *position)
Definition: FormatString.h:504
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:1035
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:1033
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>.