• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // FormatString.cpp - Common stuff for handling printf/scanf formats -*- 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 // Shared details for processing format strings of printf and scanf
11 // (and friends).
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "FormatStringParsing.h"
16 #include "clang/Basic/LangOptions.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "llvm/Support/ConvertUTF.h"
19 
20 using clang::analyze_format_string::ArgType;
21 using clang::analyze_format_string::FormatStringHandler;
22 using clang::analyze_format_string::FormatSpecifier;
23 using clang::analyze_format_string::LengthModifier;
24 using clang::analyze_format_string::OptionalAmount;
25 using clang::analyze_format_string::PositionContext;
26 using clang::analyze_format_string::ConversionSpecifier;
27 using namespace clang;
28 
29 // Key function to FormatStringHandler.
~FormatStringHandler()30 FormatStringHandler::~FormatStringHandler() {}
31 
32 //===----------------------------------------------------------------------===//
33 // Functions for parsing format strings components in both printf and
34 // scanf format strings.
35 //===----------------------------------------------------------------------===//
36 
37 OptionalAmount
ParseAmount(const char * & Beg,const char * E)38 clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
39   const char *I = Beg;
40   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
41 
42   unsigned accumulator = 0;
43   bool hasDigits = false;
44 
45   for ( ; I != E; ++I) {
46     char c = *I;
47     if (c >= '0' && c <= '9') {
48       hasDigits = true;
49       accumulator = (accumulator * 10) + (c - '0');
50       continue;
51     }
52 
53     if (hasDigits)
54       return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
55           false);
56 
57     break;
58   }
59 
60   return OptionalAmount();
61 }
62 
63 OptionalAmount
ParseNonPositionAmount(const char * & Beg,const char * E,unsigned & argIndex)64 clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
65                                                      const char *E,
66                                                      unsigned &argIndex) {
67   if (*Beg == '*') {
68     ++Beg;
69     return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
70   }
71 
72   return ParseAmount(Beg, E);
73 }
74 
75 OptionalAmount
ParsePositionAmount(FormatStringHandler & H,const char * Start,const char * & Beg,const char * E,PositionContext p)76 clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
77                                                   const char *Start,
78                                                   const char *&Beg,
79                                                   const char *E,
80                                                   PositionContext p) {
81   if (*Beg == '*') {
82     const char *I = Beg + 1;
83     const OptionalAmount &Amt = ParseAmount(I, E);
84 
85     if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
86       H.HandleInvalidPosition(Beg, I - Beg, p);
87       return OptionalAmount(false);
88     }
89 
90     if (I == E) {
91       // No more characters left?
92       H.HandleIncompleteSpecifier(Start, E - Start);
93       return OptionalAmount(false);
94     }
95 
96     assert(Amt.getHowSpecified() == OptionalAmount::Constant);
97 
98     if (*I == '$') {
99       // Handle positional arguments
100 
101       // Special case: '*0$', since this is an easy mistake.
102       if (Amt.getConstantAmount() == 0) {
103         H.HandleZeroPosition(Beg, I - Beg + 1);
104         return OptionalAmount(false);
105       }
106 
107       const char *Tmp = Beg;
108       Beg = ++I;
109 
110       return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
111                             Tmp, 0, true);
112     }
113 
114     H.HandleInvalidPosition(Beg, I - Beg, p);
115     return OptionalAmount(false);
116   }
117 
118   return ParseAmount(Beg, E);
119 }
120 
121 
122 bool
ParseFieldWidth(FormatStringHandler & H,FormatSpecifier & CS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)123 clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
124                                               FormatSpecifier &CS,
125                                               const char *Start,
126                                               const char *&Beg, const char *E,
127                                               unsigned *argIndex) {
128   // FIXME: Support negative field widths.
129   if (argIndex) {
130     CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
131   }
132   else {
133     const OptionalAmount Amt =
134       ParsePositionAmount(H, Start, Beg, E,
135                           analyze_format_string::FieldWidthPos);
136 
137     if (Amt.isInvalid())
138       return true;
139     CS.setFieldWidth(Amt);
140   }
141   return false;
142 }
143 
144 bool
ParseArgPosition(FormatStringHandler & H,FormatSpecifier & FS,const char * Start,const char * & Beg,const char * E)145 clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
146                                                FormatSpecifier &FS,
147                                                const char *Start,
148                                                const char *&Beg,
149                                                const char *E) {
150   const char *I = Beg;
151 
152   const OptionalAmount &Amt = ParseAmount(I, E);
153 
154   if (I == E) {
155     // No more characters left?
156     H.HandleIncompleteSpecifier(Start, E - Start);
157     return true;
158   }
159 
160   if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
161     // Warn that positional arguments are non-standard.
162     H.HandlePosition(Start, I - Start);
163 
164     // Special case: '%0$', since this is an easy mistake.
165     if (Amt.getConstantAmount() == 0) {
166       H.HandleZeroPosition(Start, I - Start);
167       return true;
168     }
169 
170     FS.setArgIndex(Amt.getConstantAmount() - 1);
171     FS.setUsesPositionalArg();
172     // Update the caller's pointer if we decided to consume
173     // these characters.
174     Beg = I;
175     return false;
176   }
177 
178   return false;
179 }
180 
181 bool
ParseLengthModifier(FormatSpecifier & FS,const char * & I,const char * E,const LangOptions & LO,bool IsScanf)182 clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
183                                                   const char *&I,
184                                                   const char *E,
185                                                   const LangOptions &LO,
186                                                   bool IsScanf) {
187   LengthModifier::Kind lmKind = LengthModifier::None;
188   const char *lmPosition = I;
189   switch (*I) {
190     default:
191       return false;
192     case 'h':
193       ++I;
194       if (I != E && *I == 'h') {
195         ++I;
196         lmKind = LengthModifier::AsChar;
197       } else {
198         lmKind = LengthModifier::AsShort;
199       }
200       break;
201     case 'l':
202       ++I;
203       if (I != E && *I == 'l') {
204         ++I;
205         lmKind = LengthModifier::AsLongLong;
206       } else {
207         lmKind = LengthModifier::AsLong;
208       }
209       break;
210     case 'j': lmKind = LengthModifier::AsIntMax;     ++I; break;
211     case 'z': lmKind = LengthModifier::AsSizeT;      ++I; break;
212     case 't': lmKind = LengthModifier::AsPtrDiff;    ++I; break;
213     case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
214     case 'q': lmKind = LengthModifier::AsQuad;       ++I; break;
215     case 'a':
216       if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
217         // For scanf in C90, look at the next character to see if this should
218         // be parsed as the GNU extension 'a' length modifier. If not, this
219         // will be parsed as a conversion specifier.
220         ++I;
221         if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
222           lmKind = LengthModifier::AsAllocate;
223           break;
224         }
225         --I;
226       }
227       return false;
228     case 'm':
229       if (IsScanf) {
230         lmKind = LengthModifier::AsMAllocate;
231         ++I;
232         break;
233       }
234       return false;
235     // printf: AsInt64, AsInt32, AsInt3264
236     // scanf:  AsInt64
237     case 'I':
238       if (I + 1 != E && I + 2 != E) {
239         if (I[1] == '6' && I[2] == '4') {
240           I += 3;
241           lmKind = LengthModifier::AsInt64;
242           break;
243         }
244         if (IsScanf)
245           return false;
246 
247         if (I[1] == '3' && I[2] == '2') {
248           I += 3;
249           lmKind = LengthModifier::AsInt32;
250           break;
251         }
252       }
253       ++I;
254       lmKind = LengthModifier::AsInt3264;
255       break;
256     case 'w':
257       lmKind = LengthModifier::AsWide; ++I; break;
258   }
259   LengthModifier lm(lmPosition, lmKind);
260   FS.setLengthModifier(lm);
261   return true;
262 }
263 
ParseUTF8InvalidSpecifier(const char * SpecifierBegin,const char * FmtStrEnd,unsigned & Len)264 bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
265     const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
266   if (SpecifierBegin + 1 >= FmtStrEnd)
267     return false;
268 
269   const UTF8 *SB = reinterpret_cast<const UTF8 *>(SpecifierBegin + 1);
270   const UTF8 *SE = reinterpret_cast<const UTF8 *>(FmtStrEnd);
271   const char FirstByte = *SB;
272 
273   // If the invalid specifier is a multibyte UTF-8 string, return the
274   // total length accordingly so that the conversion specifier can be
275   // properly updated to reflect a complete UTF-8 specifier.
276   unsigned NumBytes = getNumBytesForUTF8(FirstByte);
277   if (NumBytes == 1)
278     return false;
279   if (SB + NumBytes > SE)
280     return false;
281 
282   Len = NumBytes + 1;
283   return true;
284 }
285 
286 //===----------------------------------------------------------------------===//
287 // Methods on ArgType.
288 //===----------------------------------------------------------------------===//
289 
290 clang::analyze_format_string::ArgType::MatchKind
matchesType(ASTContext & C,QualType argTy) const291 ArgType::matchesType(ASTContext &C, QualType argTy) const {
292   if (Ptr) {
293     // It has to be a pointer.
294     const PointerType *PT = argTy->getAs<PointerType>();
295     if (!PT)
296       return NoMatch;
297 
298     // We cannot write through a const qualified pointer.
299     if (PT->getPointeeType().isConstQualified())
300       return NoMatch;
301 
302     argTy = PT->getPointeeType();
303   }
304 
305   switch (K) {
306     case InvalidTy:
307       llvm_unreachable("ArgType must be valid");
308 
309     case UnknownTy:
310       return Match;
311 
312     case AnyCharTy: {
313       if (const EnumType *ETy = argTy->getAs<EnumType>())
314         argTy = ETy->getDecl()->getIntegerType();
315 
316       if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
317         switch (BT->getKind()) {
318           default:
319             break;
320           case BuiltinType::Char_S:
321           case BuiltinType::SChar:
322           case BuiltinType::UChar:
323           case BuiltinType::Char_U:
324             return Match;
325         }
326       return NoMatch;
327     }
328 
329     case SpecificTy: {
330       if (const EnumType *ETy = argTy->getAs<EnumType>())
331         argTy = ETy->getDecl()->getIntegerType();
332       argTy = C.getCanonicalType(argTy).getUnqualifiedType();
333 
334       if (T == argTy)
335         return Match;
336       // Check for "compatible types".
337       if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
338         switch (BT->getKind()) {
339           default:
340             break;
341           case BuiltinType::Char_S:
342           case BuiltinType::SChar:
343           case BuiltinType::Char_U:
344           case BuiltinType::UChar:
345             return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match
346                                                                 : NoMatch;
347           case BuiltinType::Short:
348             return T == C.UnsignedShortTy ? Match : NoMatch;
349           case BuiltinType::UShort:
350             return T == C.ShortTy ? Match : NoMatch;
351           case BuiltinType::Int:
352             return T == C.UnsignedIntTy ? Match : NoMatch;
353           case BuiltinType::UInt:
354             return T == C.IntTy ? Match : NoMatch;
355           case BuiltinType::Long:
356             return T == C.UnsignedLongTy ? Match : NoMatch;
357           case BuiltinType::ULong:
358             return T == C.LongTy ? Match : NoMatch;
359           case BuiltinType::LongLong:
360             return T == C.UnsignedLongLongTy ? Match : NoMatch;
361           case BuiltinType::ULongLong:
362             return T == C.LongLongTy ? Match : NoMatch;
363         }
364       return NoMatch;
365     }
366 
367     case CStrTy: {
368       const PointerType *PT = argTy->getAs<PointerType>();
369       if (!PT)
370         return NoMatch;
371       QualType pointeeTy = PT->getPointeeType();
372       if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
373         switch (BT->getKind()) {
374           case BuiltinType::Void:
375           case BuiltinType::Char_U:
376           case BuiltinType::UChar:
377           case BuiltinType::Char_S:
378           case BuiltinType::SChar:
379             return Match;
380           default:
381             break;
382         }
383 
384       return NoMatch;
385     }
386 
387     case WCStrTy: {
388       const PointerType *PT = argTy->getAs<PointerType>();
389       if (!PT)
390         return NoMatch;
391       QualType pointeeTy =
392         C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
393       return pointeeTy == C.getWideCharType() ? Match : NoMatch;
394     }
395 
396     case WIntTy: {
397 
398       QualType PromoArg =
399         argTy->isPromotableIntegerType()
400           ? C.getPromotedIntegerType(argTy) : argTy;
401 
402       QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
403       PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
404 
405       // If the promoted argument is the corresponding signed type of the
406       // wint_t type, then it should match.
407       if (PromoArg->hasSignedIntegerRepresentation() &&
408           C.getCorrespondingUnsignedType(PromoArg) == WInt)
409         return Match;
410 
411       return WInt == PromoArg ? Match : NoMatch;
412     }
413 
414     case CPointerTy:
415       if (argTy->isVoidPointerType()) {
416         return Match;
417       } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
418             argTy->isBlockPointerType() || argTy->isNullPtrType()) {
419         return NoMatchPedantic;
420       } else {
421         return NoMatch;
422       }
423 
424     case ObjCPointerTy: {
425       if (argTy->getAs<ObjCObjectPointerType>() ||
426           argTy->getAs<BlockPointerType>())
427         return Match;
428 
429       // Handle implicit toll-free bridging.
430       if (const PointerType *PT = argTy->getAs<PointerType>()) {
431         // Things such as CFTypeRef are really just opaque pointers
432         // to C structs representing CF types that can often be bridged
433         // to Objective-C objects.  Since the compiler doesn't know which
434         // structs can be toll-free bridged, we just accept them all.
435         QualType pointee = PT->getPointeeType();
436         if (pointee->getAsStructureType() || pointee->isVoidType())
437           return Match;
438       }
439       return NoMatch;
440     }
441   }
442 
443   llvm_unreachable("Invalid ArgType Kind!");
444 }
445 
getRepresentativeType(ASTContext & C) const446 QualType ArgType::getRepresentativeType(ASTContext &C) const {
447   QualType Res;
448   switch (K) {
449     case InvalidTy:
450       llvm_unreachable("No representative type for Invalid ArgType");
451     case UnknownTy:
452       llvm_unreachable("No representative type for Unknown ArgType");
453     case AnyCharTy:
454       Res = C.CharTy;
455       break;
456     case SpecificTy:
457       Res = T;
458       break;
459     case CStrTy:
460       Res = C.getPointerType(C.CharTy);
461       break;
462     case WCStrTy:
463       Res = C.getPointerType(C.getWideCharType());
464       break;
465     case ObjCPointerTy:
466       Res = C.ObjCBuiltinIdTy;
467       break;
468     case CPointerTy:
469       Res = C.VoidPtrTy;
470       break;
471     case WIntTy: {
472       Res = C.getWIntType();
473       break;
474     }
475   }
476 
477   if (Ptr)
478     Res = C.getPointerType(Res);
479   return Res;
480 }
481 
getRepresentativeTypeName(ASTContext & C) const482 std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
483   std::string S = getRepresentativeType(C).getAsString();
484 
485   std::string Alias;
486   if (Name) {
487     // Use a specific name for this type, e.g. "size_t".
488     Alias = Name;
489     if (Ptr) {
490       // If ArgType is actually a pointer to T, append an asterisk.
491       Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";
492     }
493     // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
494     if (S == Alias)
495       Alias.clear();
496   }
497 
498   if (!Alias.empty())
499     return std::string("'") + Alias + "' (aka '" + S + "')";
500   return std::string("'") + S + "'";
501 }
502 
503 
504 //===----------------------------------------------------------------------===//
505 // Methods on OptionalAmount.
506 //===----------------------------------------------------------------------===//
507 
508 ArgType
getArgType(ASTContext & Ctx) const509 analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
510   return Ctx.IntTy;
511 }
512 
513 //===----------------------------------------------------------------------===//
514 // Methods on LengthModifier.
515 //===----------------------------------------------------------------------===//
516 
517 const char *
toString() const518 analyze_format_string::LengthModifier::toString() const {
519   switch (kind) {
520   case AsChar:
521     return "hh";
522   case AsShort:
523     return "h";
524   case AsLong: // or AsWideChar
525     return "l";
526   case AsLongLong:
527     return "ll";
528   case AsQuad:
529     return "q";
530   case AsIntMax:
531     return "j";
532   case AsSizeT:
533     return "z";
534   case AsPtrDiff:
535     return "t";
536   case AsInt32:
537     return "I32";
538   case AsInt3264:
539     return "I";
540   case AsInt64:
541     return "I64";
542   case AsLongDouble:
543     return "L";
544   case AsAllocate:
545     return "a";
546   case AsMAllocate:
547     return "m";
548   case AsWide:
549     return "w";
550   case None:
551     return "";
552   }
553   return nullptr;
554 }
555 
556 //===----------------------------------------------------------------------===//
557 // Methods on ConversionSpecifier.
558 //===----------------------------------------------------------------------===//
559 
toString() const560 const char *ConversionSpecifier::toString() const {
561   switch (kind) {
562   case dArg: return "d";
563   case DArg: return "D";
564   case iArg: return "i";
565   case oArg: return "o";
566   case OArg: return "O";
567   case uArg: return "u";
568   case UArg: return "U";
569   case xArg: return "x";
570   case XArg: return "X";
571   case fArg: return "f";
572   case FArg: return "F";
573   case eArg: return "e";
574   case EArg: return "E";
575   case gArg: return "g";
576   case GArg: return "G";
577   case aArg: return "a";
578   case AArg: return "A";
579   case cArg: return "c";
580   case sArg: return "s";
581   case pArg: return "p";
582   case nArg: return "n";
583   case PercentArg:  return "%";
584   case ScanListArg: return "[";
585   case InvalidSpecifier: return nullptr;
586 
587   // POSIX unicode extensions.
588   case CArg: return "C";
589   case SArg: return "S";
590 
591   // Objective-C specific specifiers.
592   case ObjCObjArg: return "@";
593 
594   // FreeBSD kernel specific specifiers.
595   case FreeBSDbArg: return "b";
596   case FreeBSDDArg: return "D";
597   case FreeBSDrArg: return "r";
598   case FreeBSDyArg: return "y";
599 
600   // GlibC specific specifiers.
601   case PrintErrno: return "m";
602 
603   // MS specific specifiers.
604   case ZArg: return "Z";
605   }
606   return nullptr;
607 }
608 
609 Optional<ConversionSpecifier>
getStandardSpecifier() const610 ConversionSpecifier::getStandardSpecifier() const {
611   ConversionSpecifier::Kind NewKind;
612 
613   switch (getKind()) {
614   default:
615     return None;
616   case DArg:
617     NewKind = dArg;
618     break;
619   case UArg:
620     NewKind = uArg;
621     break;
622   case OArg:
623     NewKind = oArg;
624     break;
625   }
626 
627   ConversionSpecifier FixedCS(*this);
628   FixedCS.setKind(NewKind);
629   return FixedCS;
630 }
631 
632 //===----------------------------------------------------------------------===//
633 // Methods on OptionalAmount.
634 //===----------------------------------------------------------------------===//
635 
toString(raw_ostream & os) const636 void OptionalAmount::toString(raw_ostream &os) const {
637   switch (hs) {
638   case Invalid:
639   case NotSpecified:
640     return;
641   case Arg:
642     if (UsesDotPrefix)
643         os << ".";
644     if (usesPositionalArg())
645       os << "*" << getPositionalArgIndex() << "$";
646     else
647       os << "*";
648     break;
649   case Constant:
650     if (UsesDotPrefix)
651         os << ".";
652     os << amt;
653     break;
654   }
655 }
656 
hasValidLengthModifier(const TargetInfo & Target) const657 bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
658   switch (LM.getKind()) {
659     case LengthModifier::None:
660       return true;
661 
662     // Handle most integer flags
663     case LengthModifier::AsShort:
664       if (Target.getTriple().isOSMSVCRT()) {
665         switch (CS.getKind()) {
666           case ConversionSpecifier::cArg:
667           case ConversionSpecifier::CArg:
668           case ConversionSpecifier::sArg:
669           case ConversionSpecifier::SArg:
670           case ConversionSpecifier::ZArg:
671             return true;
672           default:
673             break;
674         }
675       }
676       // Fall through.
677     case LengthModifier::AsChar:
678     case LengthModifier::AsLongLong:
679     case LengthModifier::AsQuad:
680     case LengthModifier::AsIntMax:
681     case LengthModifier::AsSizeT:
682     case LengthModifier::AsPtrDiff:
683       switch (CS.getKind()) {
684         case ConversionSpecifier::dArg:
685         case ConversionSpecifier::DArg:
686         case ConversionSpecifier::iArg:
687         case ConversionSpecifier::oArg:
688         case ConversionSpecifier::OArg:
689         case ConversionSpecifier::uArg:
690         case ConversionSpecifier::UArg:
691         case ConversionSpecifier::xArg:
692         case ConversionSpecifier::XArg:
693         case ConversionSpecifier::nArg:
694           return true;
695         case ConversionSpecifier::FreeBSDrArg:
696         case ConversionSpecifier::FreeBSDyArg:
697           return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();
698         default:
699           return false;
700       }
701 
702     // Handle 'l' flag
703     case LengthModifier::AsLong: // or AsWideChar
704       switch (CS.getKind()) {
705         case ConversionSpecifier::dArg:
706         case ConversionSpecifier::DArg:
707         case ConversionSpecifier::iArg:
708         case ConversionSpecifier::oArg:
709         case ConversionSpecifier::OArg:
710         case ConversionSpecifier::uArg:
711         case ConversionSpecifier::UArg:
712         case ConversionSpecifier::xArg:
713         case ConversionSpecifier::XArg:
714         case ConversionSpecifier::aArg:
715         case ConversionSpecifier::AArg:
716         case ConversionSpecifier::fArg:
717         case ConversionSpecifier::FArg:
718         case ConversionSpecifier::eArg:
719         case ConversionSpecifier::EArg:
720         case ConversionSpecifier::gArg:
721         case ConversionSpecifier::GArg:
722         case ConversionSpecifier::nArg:
723         case ConversionSpecifier::cArg:
724         case ConversionSpecifier::sArg:
725         case ConversionSpecifier::ScanListArg:
726         case ConversionSpecifier::ZArg:
727           return true;
728         case ConversionSpecifier::FreeBSDrArg:
729         case ConversionSpecifier::FreeBSDyArg:
730           return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();
731         default:
732           return false;
733       }
734 
735     case LengthModifier::AsLongDouble:
736       switch (CS.getKind()) {
737         case ConversionSpecifier::aArg:
738         case ConversionSpecifier::AArg:
739         case ConversionSpecifier::fArg:
740         case ConversionSpecifier::FArg:
741         case ConversionSpecifier::eArg:
742         case ConversionSpecifier::EArg:
743         case ConversionSpecifier::gArg:
744         case ConversionSpecifier::GArg:
745           return true;
746         // GNU libc extension.
747         case ConversionSpecifier::dArg:
748         case ConversionSpecifier::iArg:
749         case ConversionSpecifier::oArg:
750         case ConversionSpecifier::uArg:
751         case ConversionSpecifier::xArg:
752         case ConversionSpecifier::XArg:
753           return !Target.getTriple().isOSDarwin() &&
754                  !Target.getTriple().isOSWindows();
755         default:
756           return false;
757       }
758 
759     case LengthModifier::AsAllocate:
760       switch (CS.getKind()) {
761         case ConversionSpecifier::sArg:
762         case ConversionSpecifier::SArg:
763         case ConversionSpecifier::ScanListArg:
764           return true;
765         default:
766           return false;
767       }
768 
769     case LengthModifier::AsMAllocate:
770       switch (CS.getKind()) {
771         case ConversionSpecifier::cArg:
772         case ConversionSpecifier::CArg:
773         case ConversionSpecifier::sArg:
774         case ConversionSpecifier::SArg:
775         case ConversionSpecifier::ScanListArg:
776           return true;
777         default:
778           return false;
779       }
780     case LengthModifier::AsInt32:
781     case LengthModifier::AsInt3264:
782     case LengthModifier::AsInt64:
783       switch (CS.getKind()) {
784         case ConversionSpecifier::dArg:
785         case ConversionSpecifier::iArg:
786         case ConversionSpecifier::oArg:
787         case ConversionSpecifier::uArg:
788         case ConversionSpecifier::xArg:
789         case ConversionSpecifier::XArg:
790           return Target.getTriple().isOSMSVCRT();
791         default:
792           return false;
793       }
794     case LengthModifier::AsWide:
795       switch (CS.getKind()) {
796         case ConversionSpecifier::cArg:
797         case ConversionSpecifier::CArg:
798         case ConversionSpecifier::sArg:
799         case ConversionSpecifier::SArg:
800         case ConversionSpecifier::ZArg:
801           return Target.getTriple().isOSMSVCRT();
802         default:
803           return false;
804       }
805   }
806   llvm_unreachable("Invalid LengthModifier Kind!");
807 }
808 
hasStandardLengthModifier() const809 bool FormatSpecifier::hasStandardLengthModifier() const {
810   switch (LM.getKind()) {
811     case LengthModifier::None:
812     case LengthModifier::AsChar:
813     case LengthModifier::AsShort:
814     case LengthModifier::AsLong:
815     case LengthModifier::AsLongLong:
816     case LengthModifier::AsIntMax:
817     case LengthModifier::AsSizeT:
818     case LengthModifier::AsPtrDiff:
819     case LengthModifier::AsLongDouble:
820       return true;
821     case LengthModifier::AsAllocate:
822     case LengthModifier::AsMAllocate:
823     case LengthModifier::AsQuad:
824     case LengthModifier::AsInt32:
825     case LengthModifier::AsInt3264:
826     case LengthModifier::AsInt64:
827     case LengthModifier::AsWide:
828       return false;
829   }
830   llvm_unreachable("Invalid LengthModifier Kind!");
831 }
832 
hasStandardConversionSpecifier(const LangOptions & LangOpt) const833 bool FormatSpecifier::hasStandardConversionSpecifier(
834     const LangOptions &LangOpt) const {
835   switch (CS.getKind()) {
836     case ConversionSpecifier::cArg:
837     case ConversionSpecifier::dArg:
838     case ConversionSpecifier::iArg:
839     case ConversionSpecifier::oArg:
840     case ConversionSpecifier::uArg:
841     case ConversionSpecifier::xArg:
842     case ConversionSpecifier::XArg:
843     case ConversionSpecifier::fArg:
844     case ConversionSpecifier::FArg:
845     case ConversionSpecifier::eArg:
846     case ConversionSpecifier::EArg:
847     case ConversionSpecifier::gArg:
848     case ConversionSpecifier::GArg:
849     case ConversionSpecifier::aArg:
850     case ConversionSpecifier::AArg:
851     case ConversionSpecifier::sArg:
852     case ConversionSpecifier::pArg:
853     case ConversionSpecifier::nArg:
854     case ConversionSpecifier::ObjCObjArg:
855     case ConversionSpecifier::ScanListArg:
856     case ConversionSpecifier::PercentArg:
857       return true;
858     case ConversionSpecifier::CArg:
859     case ConversionSpecifier::SArg:
860       return LangOpt.ObjC1 || LangOpt.ObjC2;
861     case ConversionSpecifier::InvalidSpecifier:
862     case ConversionSpecifier::FreeBSDbArg:
863     case ConversionSpecifier::FreeBSDDArg:
864     case ConversionSpecifier::FreeBSDrArg:
865     case ConversionSpecifier::FreeBSDyArg:
866     case ConversionSpecifier::PrintErrno:
867     case ConversionSpecifier::DArg:
868     case ConversionSpecifier::OArg:
869     case ConversionSpecifier::UArg:
870     case ConversionSpecifier::ZArg:
871       return false;
872   }
873   llvm_unreachable("Invalid ConversionSpecifier Kind!");
874 }
875 
hasStandardLengthConversionCombination() const876 bool FormatSpecifier::hasStandardLengthConversionCombination() const {
877   if (LM.getKind() == LengthModifier::AsLongDouble) {
878     switch(CS.getKind()) {
879         case ConversionSpecifier::dArg:
880         case ConversionSpecifier::iArg:
881         case ConversionSpecifier::oArg:
882         case ConversionSpecifier::uArg:
883         case ConversionSpecifier::xArg:
884         case ConversionSpecifier::XArg:
885           return false;
886         default:
887           return true;
888     }
889   }
890   return true;
891 }
892 
getCorrectedLengthModifier() const893 Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const {
894   if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
895     if (LM.getKind() == LengthModifier::AsLongDouble ||
896         LM.getKind() == LengthModifier::AsQuad) {
897       LengthModifier FixedLM(LM);
898       FixedLM.setKind(LengthModifier::AsLongLong);
899       return FixedLM;
900     }
901   }
902 
903   return None;
904 }
905 
namedTypeToLengthModifier(QualType QT,LengthModifier & LM)906 bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
907                                                 LengthModifier &LM) {
908   assert(isa<TypedefType>(QT) && "Expected a TypedefType");
909   const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();
910 
911   for (;;) {
912     const IdentifierInfo *Identifier = Typedef->getIdentifier();
913     if (Identifier->getName() == "size_t") {
914       LM.setKind(LengthModifier::AsSizeT);
915       return true;
916     } else if (Identifier->getName() == "ssize_t") {
917       // Not C99, but common in Unix.
918       LM.setKind(LengthModifier::AsSizeT);
919       return true;
920     } else if (Identifier->getName() == "intmax_t") {
921       LM.setKind(LengthModifier::AsIntMax);
922       return true;
923     } else if (Identifier->getName() == "uintmax_t") {
924       LM.setKind(LengthModifier::AsIntMax);
925       return true;
926     } else if (Identifier->getName() == "ptrdiff_t") {
927       LM.setKind(LengthModifier::AsPtrDiff);
928       return true;
929     }
930 
931     QualType T = Typedef->getUnderlyingType();
932     if (!isa<TypedefType>(T))
933       break;
934 
935     Typedef = cast<TypedefType>(T)->getDecl();
936   }
937   return false;
938 }
939