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