clang  3.7.0
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 
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  // Look for flags (if any).
123  bool hasMore = true;
124  for ( ; I != E; ++I) {
125  switch (*I) {
126  default: hasMore = false; break;
127  case '\'':
128  // FIXME: POSIX specific. Always accept?
129  FS.setHasThousandsGrouping(I);
130  break;
131  case '-': FS.setIsLeftJustified(I); break;
132  case '+': FS.setHasPlusPrefix(I); break;
133  case ' ': FS.setHasSpacePrefix(I); break;
134  case '#': FS.setHasAlternativeForm(I); break;
135  case '0': FS.setHasLeadingZeros(I); break;
136  }
137  if (!hasMore)
138  break;
139  }
140 
141  if (I == E) {
142  // No more characters left?
143  if (Warn)
144  H.HandleIncompleteSpecifier(Start, E - Start);
145  return true;
146  }
147 
148  // Look for the field width (if any).
149  if (ParseFieldWidth(H, FS, Start, I, E,
150  FS.usesPositionalArg() ? nullptr : &argIndex))
151  return true;
152 
153  if (I == E) {
154  // No more characters left?
155  if (Warn)
156  H.HandleIncompleteSpecifier(Start, E - Start);
157  return true;
158  }
159 
160  // Look for the precision (if any).
161  if (*I == '.') {
162  ++I;
163  if (I == E) {
164  if (Warn)
165  H.HandleIncompleteSpecifier(Start, E - Start);
166  return true;
167  }
168 
169  if (ParsePrecision(H, FS, Start, I, E,
170  FS.usesPositionalArg() ? nullptr : &argIndex))
171  return true;
172 
173  if (I == E) {
174  // No more characters left?
175  if (Warn)
176  H.HandleIncompleteSpecifier(Start, E - Start);
177  return true;
178  }
179  }
180 
181  // Look for the length modifier.
182  if (ParseLengthModifier(FS, I, E, LO) && I == E) {
183  // No more characters left?
184  if (Warn)
185  H.HandleIncompleteSpecifier(Start, E - Start);
186  return true;
187  }
188 
189  // Look for the Objective-C modifier flags, if any.
190  // We parse these here, even if they don't apply to
191  // the conversion specifier, and then emit an error
192  // later if the conversion specifier isn't '@'. This
193  // enables better recovery, and we don't know if
194  // these flags are applicable until later.
195  const char *ObjCModifierFlagsStart = nullptr,
196  *ObjCModifierFlagsEnd = nullptr;
197  if (*I == '[') {
198  ObjCModifierFlagsStart = I;
199  ++I;
200  auto flagStart = I;
201  for (;; ++I) {
202  ObjCModifierFlagsEnd = I;
203  if (I == E) {
204  if (Warn)
205  H.HandleIncompleteSpecifier(Start, E - Start);
206  return true;
207  }
208  // Did we find the closing ']'?
209  if (*I == ']') {
210  if (ParseObjCFlags(H, FS, flagStart, I, Warn))
211  return true;
212  ++I;
213  break;
214  }
215  // There are no separators defined yet for multiple
216  // Objective-C modifier flags. When those are
217  // defined, this is the place to check.
218  }
219  }
220 
221  if (*I == '\0') {
222  // Detect spurious null characters, which are likely errors.
223  H.HandleNullChar(I);
224  return true;
225  }
226 
227  // Finally, look for the conversion specifier.
228  const char *conversionPosition = I++;
230  switch (*conversionPosition) {
231  default:
232  break;
233  // C99: 7.19.6.1 (section 8).
234  case '%': k = ConversionSpecifier::PercentArg; break;
235  case 'A': k = ConversionSpecifier::AArg; break;
236  case 'E': k = ConversionSpecifier::EArg; break;
237  case 'F': k = ConversionSpecifier::FArg; break;
238  case 'G': k = ConversionSpecifier::GArg; break;
239  case 'X': k = ConversionSpecifier::XArg; break;
240  case 'a': k = ConversionSpecifier::aArg; break;
241  case 'c': k = ConversionSpecifier::cArg; break;
242  case 'd': k = ConversionSpecifier::dArg; break;
243  case 'e': k = ConversionSpecifier::eArg; break;
244  case 'f': k = ConversionSpecifier::fArg; break;
245  case 'g': k = ConversionSpecifier::gArg; break;
246  case 'i': k = ConversionSpecifier::iArg; break;
247  case 'n': k = ConversionSpecifier::nArg; break;
248  case 'o': k = ConversionSpecifier::oArg; break;
249  case 'p': k = ConversionSpecifier::pArg; break;
250  case 's': k = ConversionSpecifier::sArg; break;
251  case 'u': k = ConversionSpecifier::uArg; break;
252  case 'x': k = ConversionSpecifier::xArg; break;
253  // POSIX specific.
254  case 'C': k = ConversionSpecifier::CArg; break;
255  case 'S': k = ConversionSpecifier::SArg; break;
256  // Objective-C.
257  case '@': k = ConversionSpecifier::ObjCObjArg; break;
258  // Glibc specific.
259  case 'm': k = ConversionSpecifier::PrintErrno; break;
260  // FreeBSD kernel specific.
261  case 'b':
262  if (isFreeBSDKPrintf)
263  k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
264  break;
265  case 'r':
266  if (isFreeBSDKPrintf)
268  break;
269  case 'y':
270  if (isFreeBSDKPrintf)
272  break;
273  // Apple-specific.
274  case 'D':
275  if (isFreeBSDKPrintf)
276  k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
277  else if (Target.getTriple().isOSDarwin())
279  break;
280  case 'O':
281  if (Target.getTriple().isOSDarwin())
283  break;
284  case 'U':
285  if (Target.getTriple().isOSDarwin())
287  break;
288  // MS specific.
289  case 'Z':
290  if (Target.getTriple().isOSMSVCRT())
292  }
293 
294  // Check to see if we used the Objective-C modifier flags with
295  // a conversion specifier other than '@'.
298  ObjCModifierFlagsStart) {
299  H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
300  ObjCModifierFlagsEnd + 1,
301  conversionPosition);
302  return true;
303  }
304 
305  PrintfConversionSpecifier CS(conversionPosition, k);
306  FS.setConversionSpecifier(CS);
307  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
308  FS.setArgIndex(argIndex++);
309  // FreeBSD kernel specific.
312  argIndex++;
313 
315  // Assume the conversion takes one argument.
316  return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
317  }
318  return PrintfSpecifierResult(Start, FS);
319 }
320 
322  const char *I,
323  const char *E,
324  const LangOptions &LO,
325  const TargetInfo &Target,
326  bool isFreeBSDKPrintf) {
327 
328  unsigned argIndex = 0;
329 
330  // Keep looking for a format specifier until we have exhausted the string.
331  while (I != E) {
332  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
333  LO, Target, true,
334  isFreeBSDKPrintf);
335  // Did a fail-stop error of any kind occur when parsing the specifier?
336  // If so, don't do any more processing.
337  if (FSR.shouldStop())
338  return true;
339  // Did we exhaust the string or encounter an error that
340  // we can recover from?
341  if (!FSR.hasValue())
342  continue;
343  // We have a format specifier. Pass it to the callback.
344  if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
345  I - FSR.getStart()))
346  return true;
347  }
348  assert(I == E && "Format string not exhausted");
349  return false;
350 }
351 
353  const char *E,
354  const LangOptions &LO,
355  const TargetInfo &Target) {
356 
357  unsigned argIndex = 0;
358 
359  // Keep looking for a %s format specifier until we have exhausted the string.
361  while (I != E) {
362  const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
363  LO, Target, false,
364  false);
365  // Did a fail-stop error of any kind occur when parsing the specifier?
366  // If so, don't do any more processing.
367  if (FSR.shouldStop())
368  return false;
369  // Did we exhaust the string or encounter an error that
370  // we can recover from?
371  if (!FSR.hasValue())
372  continue;
373  const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
374  // Return true if this a %s format specifier.
375  if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
376  return true;
377  }
378  return false;
379 }
380 
381 //===----------------------------------------------------------------------===//
382 // Methods on PrintfSpecifier.
383 //===----------------------------------------------------------------------===//
384 
385 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
386  bool IsObjCLiteral) const {
387  const PrintfConversionSpecifier &CS = getConversionSpecifier();
388 
389  if (!CS.consumesDataArgument())
390  return ArgType::Invalid();
391 
393  switch (LM.getKind()) {
395  return Ctx.IntTy;
398  return ArgType(ArgType::WIntTy, "wint_t");
400  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
401  return Ctx.IntTy;
402  default:
403  return ArgType::Invalid();
404  }
405 
406  if (CS.isIntArg())
407  switch (LM.getKind()) {
409  // GNU extension.
410  return Ctx.LongLongTy;
412  return Ctx.IntTy;
414  return ArgType(Ctx.IntTy, "__int32");
416  case LengthModifier::AsShort: return Ctx.ShortTy;
417  case LengthModifier::AsLong: return Ctx.LongTy;
420  return Ctx.LongLongTy;
422  return ArgType(Ctx.LongLongTy, "__int64");
424  return ArgType(Ctx.getIntMaxType(), "intmax_t");
426  // FIXME: How to get the corresponding signed version of size_t?
427  return ArgType();
429  return Ctx.getTargetInfo().getTriple().isArch64Bit()
430  ? ArgType(Ctx.LongLongTy, "__int64")
431  : ArgType(Ctx.IntTy, "__int32");
433  return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
437  return ArgType::Invalid();
438  }
439 
440  if (CS.isUIntArg())
441  switch (LM.getKind()) {
443  // GNU extension.
444  return Ctx.UnsignedLongLongTy;
446  return Ctx.UnsignedIntTy;
448  return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
449  case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
450  case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
451  case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
454  return Ctx.UnsignedLongLongTy;
456  return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
458  return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
460  return ArgType(Ctx.getSizeType(), "size_t");
462  return Ctx.getTargetInfo().getTriple().isArch64Bit()
463  ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
464  : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
466  // FIXME: How to get the corresponding unsigned
467  // version of ptrdiff_t?
468  return ArgType();
472  return ArgType::Invalid();
473  }
474 
475  if (CS.isDoubleArg()) {
476  if (LM.getKind() == LengthModifier::AsLongDouble)
477  return Ctx.LongDoubleTy;
478  return Ctx.DoubleTy;
479  }
480 
481  if (CS.getKind() == ConversionSpecifier::nArg) {
482  switch (LM.getKind()) {
484  return ArgType::PtrTo(Ctx.IntTy);
486  return ArgType::PtrTo(Ctx.SignedCharTy);
488  return ArgType::PtrTo(Ctx.ShortTy);
490  return ArgType::PtrTo(Ctx.LongTy);
493  return ArgType::PtrTo(Ctx.LongLongTy);
495  return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
497  return ArgType(); // FIXME: ssize_t
499  return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
501  return ArgType(); // FIXME: Is this a known extension?
508  return ArgType::Invalid();
509  }
510  }
511 
512  switch (CS.getKind()) {
514  if (LM.getKind() == LengthModifier::AsWideChar) {
515  if (IsObjCLiteral)
516  return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
517  "const unichar *");
518  return ArgType(ArgType::WCStrTy, "wchar_t *");
519  }
520  if (LM.getKind() == LengthModifier::AsWide)
521  return ArgType(ArgType::WCStrTy, "wchar_t *");
522  return ArgType::CStrTy;
524  if (IsObjCLiteral)
525  return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
526  "const unichar *");
527  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
528  LM.getKind() == LengthModifier::AsShort)
529  return ArgType::CStrTy;
530  return ArgType(ArgType::WCStrTy, "wchar_t *");
532  if (IsObjCLiteral)
533  return ArgType(Ctx.UnsignedShortTy, "unichar");
534  if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
535  LM.getKind() == LengthModifier::AsShort)
536  return Ctx.IntTy;
537  return ArgType(Ctx.WideCharTy, "wchar_t");
539  return ArgType::CPointerTy;
541  return ArgType::ObjCPointerTy;
542  default:
543  break;
544  }
545 
546  // FIXME: Handle other cases.
547  return ArgType();
548 }
549 
550 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
551  ASTContext &Ctx, bool IsObjCLiteral) {
552  // %n is different from other conversion specifiers; don't try to fix it.
553  if (CS.getKind() == ConversionSpecifier::nArg)
554  return false;
555 
556  // Handle Objective-C objects first. Note that while the '%@' specifier will
557  // not warn for structure pointer or void pointer arguments (because that's
558  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
559  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
560  if (QT->isObjCRetainableType()) {
561  if (!IsObjCLiteral)
562  return false;
563 
565 
566  // Disable irrelevant flags
567  HasThousandsGrouping = false;
568  HasPlusPrefix = false;
569  HasSpacePrefix = false;
570  HasAlternativeForm = false;
571  HasLeadingZeroes = false;
572  Precision.setHowSpecified(OptionalAmount::NotSpecified);
573  LM.setKind(LengthModifier::None);
574 
575  return true;
576  }
577 
578  // Handle strings next (char *, wchar_t *)
579  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
580  CS.setKind(ConversionSpecifier::sArg);
581 
582  // Disable irrelevant flags
583  HasAlternativeForm = 0;
584  HasLeadingZeroes = 0;
585 
586  // Set the long length modifier for wide characters
587  if (QT->getPointeeType()->isWideCharType())
588  LM.setKind(LengthModifier::AsWideChar);
589  else
590  LM.setKind(LengthModifier::None);
591 
592  return true;
593  }
594 
595  // If it's an enum, get its underlying type.
596  if (const EnumType *ETy = QT->getAs<EnumType>())
597  QT = ETy->getDecl()->getIntegerType();
598 
599  // We can only work with builtin types.
600  const BuiltinType *BT = QT->getAs<BuiltinType>();
601  if (!BT)
602  return false;
603 
604  // Set length modifier
605  switch (BT->getKind()) {
606  case BuiltinType::Bool:
607  case BuiltinType::WChar_U:
608  case BuiltinType::WChar_S:
609  case BuiltinType::Char16:
610  case BuiltinType::Char32:
611  case BuiltinType::UInt128:
612  case BuiltinType::Int128:
613  case BuiltinType::Half:
614  // Various types which are non-trivial to correct.
615  return false;
616 
617 #define SIGNED_TYPE(Id, SingletonId)
618 #define UNSIGNED_TYPE(Id, SingletonId)
619 #define FLOATING_TYPE(Id, SingletonId)
620 #define BUILTIN_TYPE(Id, SingletonId) \
621  case BuiltinType::Id:
622 #include "clang/AST/BuiltinTypes.def"
623  // Misc other stuff which doesn't make sense here.
624  return false;
625 
626  case BuiltinType::UInt:
627  case BuiltinType::Int:
628  case BuiltinType::Float:
629  case BuiltinType::Double:
630  LM.setKind(LengthModifier::None);
631  break;
632 
633  case BuiltinType::Char_U:
634  case BuiltinType::UChar:
635  case BuiltinType::Char_S:
636  case BuiltinType::SChar:
637  LM.setKind(LengthModifier::AsChar);
638  break;
639 
640  case BuiltinType::Short:
641  case BuiltinType::UShort:
642  LM.setKind(LengthModifier::AsShort);
643  break;
644 
645  case BuiltinType::Long:
646  case BuiltinType::ULong:
647  LM.setKind(LengthModifier::AsLong);
648  break;
649 
650  case BuiltinType::LongLong:
651  case BuiltinType::ULongLong:
652  LM.setKind(LengthModifier::AsLongLong);
653  break;
654 
655  case BuiltinType::LongDouble:
656  LM.setKind(LengthModifier::AsLongDouble);
657  break;
658  }
659 
660  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
661  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
662  namedTypeToLengthModifier(QT, LM);
663 
664  // If fixing the length modifier was enough, we might be done.
665  if (hasValidLengthModifier(Ctx.getTargetInfo())) {
666  // If we're going to offer a fix anyway, make sure the sign matches.
667  switch (CS.getKind()) {
670  if (QT->isSignedIntegerType())
672  break;
676  if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
678  break;
679  default:
680  // Other specifiers do not have signed/unsigned variants.
681  break;
682  }
683 
684  const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
685  if (ATR.isValid() && ATR.matchesType(Ctx, QT))
686  return true;
687  }
688 
689  // Set conversion specifier and disable any flags which do not apply to it.
690  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
691  if (!isa<TypedefType>(QT) && QT->isCharType()) {
692  CS.setKind(ConversionSpecifier::cArg);
693  LM.setKind(LengthModifier::None);
694  Precision.setHowSpecified(OptionalAmount::NotSpecified);
695  HasAlternativeForm = 0;
696  HasLeadingZeroes = 0;
697  HasPlusPrefix = 0;
698  }
699  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
700  else if (QT->isRealFloatingType()) {
701  CS.setKind(ConversionSpecifier::fArg);
702  }
703  else if (QT->isSignedIntegerType()) {
704  CS.setKind(ConversionSpecifier::dArg);
705  HasAlternativeForm = 0;
706  }
707  else if (QT->isUnsignedIntegerType()) {
708  CS.setKind(ConversionSpecifier::uArg);
709  HasAlternativeForm = 0;
710  HasPlusPrefix = 0;
711  } else {
712  llvm_unreachable("Unexpected type");
713  }
714 
715  return true;
716 }
717 
718 void PrintfSpecifier::toString(raw_ostream &os) const {
719  // Whilst some features have no defined order, we are using the order
720  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
721  os << "%";
722 
723  // Positional args
724  if (usesPositionalArg()) {
725  os << getPositionalArgIndex() << "$";
726  }
727 
728  // Conversion flags
729  if (IsLeftJustified) os << "-";
730  if (HasPlusPrefix) os << "+";
731  if (HasSpacePrefix) os << " ";
732  if (HasAlternativeForm) os << "#";
733  if (HasLeadingZeroes) os << "0";
734 
735  // Minimum field width
736  FieldWidth.toString(os);
737  // Precision
738  Precision.toString(os);
739  // Length modifier
740  os << LM.toString();
741  // Conversion specifier
742  os << CS.toString();
743 }
744 
745 bool PrintfSpecifier::hasValidPlusPrefix() const {
746  if (!HasPlusPrefix)
747  return true;
748 
749  // The plus prefix only makes sense for signed conversions
750  switch (CS.getKind()) {
764  return true;
765 
766  default:
767  return false;
768  }
769 }
770 
771 bool PrintfSpecifier::hasValidAlternativeForm() const {
772  if (!HasAlternativeForm)
773  return true;
774 
775  // Alternate form flag only valid with the oxXaAeEfFgG conversions
776  switch (CS.getKind()) {
791  return true;
792 
793  default:
794  return false;
795  }
796 }
797 
798 bool PrintfSpecifier::hasValidLeadingZeros() const {
799  if (!HasLeadingZeroes)
800  return true;
801 
802  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
803  switch (CS.getKind()) {
823  return true;
824 
825  default:
826  return false;
827  }
828 }
829 
830 bool PrintfSpecifier::hasValidSpacePrefix() const {
831  if (!HasSpacePrefix)
832  return true;
833 
834  // The space prefix only makes sense for signed conversions
835  switch (CS.getKind()) {
849  return true;
850 
851  default:
852  return false;
853  }
854 }
855 
856 bool PrintfSpecifier::hasValidLeftJustified() const {
857  if (!IsLeftJustified)
858  return true;
859 
860  // The left justified flag is valid for all conversions except n
861  switch (CS.getKind()) {
863  return false;
864 
865  default:
866  return true;
867  }
868 }
869 
870 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
871  if (!HasThousandsGrouping)
872  return true;
873 
874  switch (CS.getKind()) {
884  return true;
885  default:
886  return false;
887  }
888 }
889 
890 bool PrintfSpecifier::hasValidPrecision() const {
891  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
892  return true;
893 
894  // Precision is only valid with the diouxXaAeEfFgGs conversions
895  switch (CS.getKind()) {
916  return true;
917 
918  default:
919  return false;
920  }
921 }
922 bool PrintfSpecifier::hasValidFieldWidth() const {
923  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
924  return true;
925 
926  // The field width is valid for all conversions except n
927  switch (CS.getKind()) {
929  return false;
930 
931  default:
932  return true;
933  }
934 }
Kind getKind() const
Definition: Type.h:2006
CanQualType LongLongTy
Definition: ASTContext.h:825
bool isCharType() const
Definition: Type.cpp:1633
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition: Type.cpp:1663
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
virtual void HandleInvalidObjCModifierFlag(const char *startFlag, unsigned flagLen)
Definition: FormatString.h:627
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:825
CanQualType WideCharTy
Definition: ASTContext.h:821
bool isObjCRetainableType() const
Definition: Type.cpp:3542
virtual void HandleEmptyObjCModifierFlag(const char *startFlags, unsigned flagsLen)
Definition: FormatString.h:624
QualType withConst() const
Retrieves a version of this type with const applied. Note that this does not always yield a canonical...
CanQualType getIntMaxType() const
Return the unique type for "intmax_t" (C99 7.18.1.5), defined in <stdint.h>.
void setPrecision(const OptionalAmount &Amt)
Definition: FormatString.h:483
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:89
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
virtual bool HandleInvalidPrintfConversionSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:635
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:518
Represents the length modifier in a format string in scanf/printf.
Definition: FormatString.h:65
bool isUnsignedIntegerType() const
Definition: Type.cpp:1723
CanQualType LongDoubleTy
Definition: ASTContext.h:828
CanQualType UnsignedCharTy
Definition: ASTContext.h:826
static ArgType PtrTo(const ArgType &A)
Create an ArgType which corresponds to the type pointer to A.
Definition: FormatString.h:254
OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, unsigned &argIndex)
QualType getPointeeType() const
Definition: Type.cpp:414
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:1776
Exposes information about the current target.
CanQualType getUIntMaxType() const
Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in <stdint.h>.
CanQualType ShortTy
Definition: ASTContext.h:825
virtual void HandleNullChar(const char *nullCharacter)
Definition: FormatString.h:612
const PrintfConversionSpecifier & getConversionSpecifier() const
Definition: FormatString.h:479
CanQualType SignedCharTy
Definition: ASTContext.h:825
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:630
bool ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &CS, const char *Start, const char *&Beg, const char *E, unsigned *argIndex)
virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:642
CanQualType UnsignedShortTy
Definition: ASTContext.h:826
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:827
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isWideCharType() const
Definition: Type.cpp:1642
std::string toString(const til::SExpr *E)
void setHasObjCTechnicalTerm(const char *position)
Definition: FormatString.h:472
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>. Pointer - pointer requires t...
const T * getAs() const
Definition: Type.h:5555
CanQualType UnsignedLongTy
Definition: ASTContext.h:826
bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E, const LangOptions &LO, bool IsScanf=false)
virtual void HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen)
Definition: FormatString.h:621
Defines the clang::TargetInfo interface.
CanQualType IntTy
Definition: ASTContext.h:825
bool ParsePrintfString(FormatStringHandler &H, const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target, bool isFreeBSDKPrintf)
clang::analyze_format_string::SpecifierResult< PrintfSpecifier > PrintfSpecifierResult
bool isSignedIntegerType() const
Definition: Type.cpp:1683
CanQualType DoubleTy
Definition: ASTContext.h:828
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:826
OptionalAmount ParsePositionAmount(FormatStringHandler &H, const char *Start, const char *&Beg, const char *E, PositionContext p)
bool isPointerType() const
Definition: Type.h:5232