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