Clang Project

clang_source_code/lib/AST/PrintfFormatString.cpp
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
19using clang::analyze_format_string::ArgType;
20using clang::analyze_format_string::FormatStringHandler;
21using clang::analyze_format_string::LengthModifier;
22using clang::analyze_format_string::OptionalAmount;
23using clang::analyze_format_string::ConversionSpecifier;
24using clang::analyze_printf::PrintfSpecifier;
25
26using namespace clang;
27
28typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
29        PrintfSpecifierResult;
30
31//===----------------------------------------------------------------------===//
32// Methods for parsing format strings.
33//===----------------------------------------------------------------------===//
34
35using analyze_format_string::ParseNonPositionAmount;
36
37static bool ParsePrecision(FormatStringHandler &HPrintfSpecifier &FS,
38                           const char *Startconst char *&Begconst char *E,
39                           unsigned *argIndex) {
40  if (argIndex) {
41    FS.setPrecision(ParseNonPositionAmount(BegE*argIndex));
42  } else {
43    const OptionalAmount Amt = ParsePositionAmount(HStartBegE,
44                                           analyze_format_string::PrecisionPos);
45    if (Amt.isInvalid())
46      return true;
47    FS.setPrecision(Amt);
48  }
49  return false;
50}
51
52static bool ParseObjCFlags(FormatStringHandler &HPrintfSpecifier &FS,
53                           const char *FlagBegconst char *Ebool 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(FlagBegE  - FlagBeg);
64     else
65       H.HandleInvalidObjCModifierFlag(FlagBegE  - FlagBeg);
66   }
67   return true;
68}
69
70static 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(BegI);
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(StartE - Start);
108    return true;
109  }
110
111  PrintfSpecifier FS;
112  if (ParseArgPosition(HFSStartIE))
113    return true;
114
115  if (I == E) {
116    // No more characters left?
117    if (Warn)
118      H.HandleIncompleteSpecifier(StartE - 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<StringRef2Matches;
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(StartE - 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      defaulthasMore = falsebreak;
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(StartE - Start);
213    return true;
214  }
215
216  // Look for the field width (if any).
217  if (ParseFieldWidth(HFSStartIE,
218                      FS.usesPositionalArg() ? nullptr : &argIndex))
219    return true;
220
221  if (I == E) {
222    // No more characters left?
223    if (Warn)
224      H.HandleIncompleteSpecifier(StartE - 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(StartE - Start);
234      return true;
235    }
236
237    if (ParsePrecision(HFSStartIE,
238                       FS.usesPositionalArg() ? nullptr : &argIndex))
239      return true;
240
241    if (I == E) {
242      // No more characters left?
243      if (Warn)
244        H.HandleIncompleteSpecifier(StartE - Start);
245      return true;
246    }
247  }
248
249  if (ParseVectorModifier(HFSIELO))
250    return true;
251
252  // Look for the length modifier.
253  if (ParseLengthModifier(FSIELO) && I == E) {
254    // No more characters left?
255    if (Warn)
256      H.HandleIncompleteSpecifier(StartE - 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(StartE - Start);
277        return true;
278      }
279      // Did we find the closing ']'?
280      if (*I == ']') {
281        if (ParseObjCFlags(HFSflagStartIWarn))
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::AArgbreak;
307    case 'E'k = ConversionSpecifier::EArgbreak;
308    case 'F'k = ConversionSpecifier::FArgbreak;
309    case 'G'k = ConversionSpecifier::GArgbreak;
310    case 'X'k = ConversionSpecifier::XArgbreak;
311    case 'a'k = ConversionSpecifier::aArgbreak;
312    case 'c'k = ConversionSpecifier::cArgbreak;
313    case 'd'k = ConversionSpecifier::dArgbreak;
314    case 'e'k = ConversionSpecifier::eArgbreak;
315    case 'f'k = ConversionSpecifier::fArgbreak;
316    case 'g'k = ConversionSpecifier::gArgbreak;
317    case 'i'k = ConversionSpecifier::iArgbreak;
318    case 'n':
319      // Not handled, but reserved in OpenCL.
320      if (!LO.OpenCL)
321        k = ConversionSpecifier::nArg;
322      break;
323    case 'o'k = ConversionSpecifier::oArgbreak;
324    case 'p'k = ConversionSpecifier::pArgbreak;
325    case 's'k = ConversionSpecifier::sArgbreak;
326    case 'u'k = ConversionSpecifier::uArgbreak;
327    case 'x'k = ConversionSpecifier::xArgbreak;
328    // POSIX specific.
329    case 'C'k = ConversionSpecifier::CArgbreak;
330    case 'S'k = ConversionSpecifier::SArgbreak;
331    // Apple extension for os_log
332    case 'P':
333      k = ConversionSpecifier::PArg;
334      break;
335    // Objective-C.
336    case '@'k = ConversionSpecifier::ObjCObjArgbreak;
337    // Glibc specific.
338    case 'm'k = ConversionSpecifier::PrintErrnobreak;
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(conversionPositionk);
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(StartELen)) {
397      CS.setEndScanList(Start + Len);
398      FS.setConversionSpecifier(CS);
399    }
400    // Assume the conversion takes one argument.
401    return !H.HandleInvalidPrintfConversionSpecifier(FSStartLen);
402  }
403  return PrintfSpecifierResult(StartFS);
404}
405
406bool 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   (0) . __assert_fail ("I == E && \"Format string not exhausted\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/PrintfFormatString.cpp", 433, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(I == E && "Format string not exhausted");
434  return false;
435}
436
437bool 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//===----------------------------------------------------------------------===//
467// Methods on PrintfSpecifier.
468//===----------------------------------------------------------------------===//
469
470ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
471                                          bool IsObjCLiteralconst {
472  if (CS.getKind() == ConversionSpecifier::cArg)
473    switch (LM.getKind()) {
474      case LengthModifier::None:
475        return Ctx.IntTy;
476      case LengthModifier::AsLong:
477      case LengthModifier::AsWide:
478        return ArgType(ArgType::WIntTy"wint_t");
479      case LengthModifier::AsShort:
480        if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
481          return Ctx.IntTy;
482        LLVM_FALLTHROUGH;
483      default:
484        return ArgType::Invalid();
485    }
486
487  if (CS.isIntArg())
488    switch (LM.getKind()) {
489      case LengthModifier::AsLongDouble:
490        // GNU extension.
491        return Ctx.LongLongTy;
492      case LengthModifier::None:
493      case LengthModifier::AsShortLong:
494        return Ctx.IntTy;
495      case LengthModifier::AsInt32:
496        return ArgType(Ctx.IntTy, "__int32");
497      case LengthModifier::AsChar:
498        return ArgType::AnyCharTy;
499      case LengthModifier::AsShortreturn Ctx.ShortTy;
500      case LengthModifier::AsLongreturn Ctx.LongTy;
501      case LengthModifier::AsLongLong:
502      case LengthModifier::AsQuad:
503        return Ctx.LongLongTy;
504      case LengthModifier::AsInt64:
505        return ArgType(Ctx.LongLongTy, "__int64");
506      case LengthModifier::AsIntMax:
507        return ArgType(Ctx.getIntMaxType(), "intmax_t");
508      case LengthModifier::AsSizeT:
509        return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
510      case LengthModifier::AsInt3264:
511        return Ctx.getTargetInfo().getTriple().isArch64Bit()
512                   ? ArgType(Ctx.LongLongTy, "__int64")
513                   : ArgType(Ctx.IntTy, "__int32");
514      case LengthModifier::AsPtrDiff:
515        return ArgType::makePtrdiffT(
516            ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
517      case LengthModifier::AsAllocate:
518      case LengthModifier::AsMAllocate:
519      case LengthModifier::AsWide:
520        return ArgType::Invalid();
521    }
522
523  if (CS.isUIntArg())
524    switch (LM.getKind()) {
525      case LengthModifier::AsLongDouble:
526        // GNU extension.
527        return Ctx.UnsignedLongLongTy;
528      case LengthModifier::None:
529      case LengthModifier::AsShortLong:
530        return Ctx.UnsignedIntTy;
531      case LengthModifier::AsInt32:
532        return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
533      case LengthModifier::AsCharreturn Ctx.UnsignedCharTy;
534      case LengthModifier::AsShortreturn Ctx.UnsignedShortTy;
535      case LengthModifier::AsLongreturn Ctx.UnsignedLongTy;
536      case LengthModifier::AsLongLong:
537      case LengthModifier::AsQuad:
538        return Ctx.UnsignedLongLongTy;
539      case LengthModifier::AsInt64:
540        return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
541      case LengthModifier::AsIntMax:
542        return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
543      case LengthModifier::AsSizeT:
544        return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
545      case LengthModifier::AsInt3264:
546        return Ctx.getTargetInfo().getTriple().isArch64Bit()
547                   ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
548                   : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
549      case LengthModifier::AsPtrDiff:
550        return ArgType::makePtrdiffT(
551            ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
552      case LengthModifier::AsAllocate:
553      case LengthModifier::AsMAllocate:
554      case LengthModifier::AsWide:
555        return ArgType::Invalid();
556    }
557
558  if (CS.isDoubleArg()) {
559    if (!VectorNumElts.isInvalid()) {
560      switch (LM.getKind()) {
561      case LengthModifier::AsShort:
562        return Ctx.HalfTy;
563      case LengthModifier::AsShortLong:
564        return Ctx.FloatTy;
565      case LengthModifier::AsLong:
566      default:
567        return Ctx.DoubleTy;
568      }
569    }
570
571    if (LM.getKind() == LengthModifier::AsLongDouble)
572      return Ctx.LongDoubleTy;
573    return Ctx.DoubleTy;
574  }
575
576  if (CS.getKind() == ConversionSpecifier::nArg) {
577    switch (LM.getKind()) {
578      case LengthModifier::None:
579        return ArgType::PtrTo(Ctx.IntTy);
580      case LengthModifier::AsChar:
581        return ArgType::PtrTo(Ctx.SignedCharTy);
582      case LengthModifier::AsShort:
583        return ArgType::PtrTo(Ctx.ShortTy);
584      case LengthModifier::AsLong:
585        return ArgType::PtrTo(Ctx.LongTy);
586      case LengthModifier::AsLongLong:
587      case LengthModifier::AsQuad:
588        return ArgType::PtrTo(Ctx.LongLongTy);
589      case LengthModifier::AsIntMax:
590        return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
591      case LengthModifier::AsSizeT:
592        return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
593      case LengthModifier::AsPtrDiff:
594        return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
595      case LengthModifier::AsLongDouble:
596        return ArgType(); // FIXME: Is this a known extension?
597      case LengthModifier::AsAllocate:
598      case LengthModifier::AsMAllocate:
599      case LengthModifier::AsInt32:
600      case LengthModifier::AsInt3264:
601      case LengthModifier::AsInt64:
602      case LengthModifier::AsWide:
603        return ArgType::Invalid();
604      case LengthModifier::AsShortLong:
605        llvm_unreachable("only used for OpenCL which doesn not handle nArg");
606    }
607  }
608
609  switch (CS.getKind()) {
610    case ConversionSpecifier::sArg:
611      if (LM.getKind() == LengthModifier::AsWideChar) {
612        if (IsObjCLiteral)
613          return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
614                         "const unichar *");
615        return ArgType(ArgType::WCStrTy"wchar_t *");
616      }
617      if (LM.getKind() == LengthModifier::AsWide)
618        return ArgType(ArgType::WCStrTy"wchar_t *");
619      return ArgType::CStrTy;
620    case ConversionSpecifier::SArg:
621      if (IsObjCLiteral)
622        return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
623                       "const unichar *");
624      if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
625          LM.getKind() == LengthModifier::AsShort)
626        return ArgType::CStrTy;
627      return ArgType(ArgType::WCStrTy"wchar_t *");
628    case ConversionSpecifier::CArg:
629      if (IsObjCLiteral)
630        return ArgType(Ctx.UnsignedShortTy, "unichar");
631      if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
632          LM.getKind() == LengthModifier::AsShort)
633        return Ctx.IntTy;
634      return ArgType(Ctx.WideCharTy, "wchar_t");
635    case ConversionSpecifier::pArg:
636    case ConversionSpecifier::PArg:
637      return ArgType::CPointerTy;
638    case ConversionSpecifier::ObjCObjArg:
639      return ArgType::ObjCPointerTy;
640    default:
641      break;
642  }
643
644  // FIXME: Handle other cases.
645  return ArgType();
646}
647
648
649ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
650                                    bool IsObjCLiteralconst {
651  const PrintfConversionSpecifier &CS = getConversionSpecifier();
652
653  if (!CS.consumesDataArgument())
654    return ArgType::Invalid();
655
656  ArgType ScalarTy = getScalarArgType(CtxIsObjCLiteral);
657  if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
658    return ScalarTy;
659
660  return ScalarTy.makeVectorType(CtxVectorNumElts.getConstantAmount());
661}
662
663bool PrintfSpecifier::fixType(QualType QTconst LangOptions &LangOpt,
664                              ASTContext &Ctxbool IsObjCLiteral) {
665  // %n is different from other conversion specifiers; don't try to fix it.
666  if (CS.getKind() == ConversionSpecifier::nArg)
667    return false;
668
669  // Handle Objective-C objects first. Note that while the '%@' specifier will
670  // not warn for structure pointer or void pointer arguments (because that's
671  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
672  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
673  if (QT->isObjCRetainableType()) {
674    if (!IsObjCLiteral)
675      return false;
676
677    CS.setKind(ConversionSpecifier::ObjCObjArg);
678
679    // Disable irrelevant flags
680    HasThousandsGrouping = false;
681    HasPlusPrefix = false;
682    HasSpacePrefix = false;
683    HasAlternativeForm = false;
684    HasLeadingZeroes = false;
685    Precision.setHowSpecified(OptionalAmount::NotSpecified);
686    LM.setKind(LengthModifier::None);
687
688    return true;
689  }
690
691  // Handle strings next (char *, wchar_t *)
692  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
693    CS.setKind(ConversionSpecifier::sArg);
694
695    // Disable irrelevant flags
696    HasAlternativeForm = 0;
697    HasLeadingZeroes = 0;
698
699    // Set the long length modifier for wide characters
700    if (QT->getPointeeType()->isWideCharType())
701      LM.setKind(LengthModifier::AsWideChar);
702    else
703      LM.setKind(LengthModifier::None);
704
705    return true;
706  }
707
708  // If it's an enum, get its underlying type.
709  if (const EnumType *ETy = QT->getAs<EnumType>())
710    QT = ETy->getDecl()->getIntegerType();
711
712  const BuiltinType *BT = QT->getAs<BuiltinType>();
713  if (!BT) {
714    const VectorType *VT = QT->getAs<VectorType>();
715    if (VT) {
716      QT = VT->getElementType();
717      BT = QT->getAs<BuiltinType>();
718      VectorNumElts = OptionalAmount(VT->getNumElements());
719    }
720  }
721
722  // We can only work with builtin types.
723  if (!BT)
724    return false;
725
726  // Set length modifier
727  switch (BT->getKind()) {
728  case BuiltinType::Bool:
729  case BuiltinType::WChar_U:
730  case BuiltinType::WChar_S:
731  case BuiltinType::Char8// FIXME: Treat like 'char'?
732  case BuiltinType::Char16:
733  case BuiltinType::Char32:
734  case BuiltinType::UInt128:
735  case BuiltinType::Int128:
736  case BuiltinType::Half:
737  case BuiltinType::Float16:
738  case BuiltinType::Float128:
739  case BuiltinType::ShortAccum:
740  case BuiltinType::Accum:
741  case BuiltinType::LongAccum:
742  case BuiltinType::UShortAccum:
743  case BuiltinType::UAccum:
744  case BuiltinType::ULongAccum:
745  case BuiltinType::ShortFract:
746  case BuiltinType::Fract:
747  case BuiltinType::LongFract:
748  case BuiltinType::UShortFract:
749  case BuiltinType::UFract:
750  case BuiltinType::ULongFract:
751  case BuiltinType::SatShortAccum:
752  case BuiltinType::SatAccum:
753  case BuiltinType::SatLongAccum:
754  case BuiltinType::SatUShortAccum:
755  case BuiltinType::SatUAccum:
756  case BuiltinType::SatULongAccum:
757  case BuiltinType::SatShortFract:
758  case BuiltinType::SatFract:
759  case BuiltinType::SatLongFract:
760  case BuiltinType::SatUShortFract:
761  case BuiltinType::SatUFract:
762  case BuiltinType::SatULongFract:
763    // Various types which are non-trivial to correct.
764    return false;
765
766#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
767  case BuiltinType::Id:
768#include "clang/Basic/OpenCLImageTypes.def"
769#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
770  case BuiltinType::Id:
771#include "clang/Basic/OpenCLExtensionTypes.def"
772#define SIGNED_TYPE(Id, SingletonId)
773#define UNSIGNED_TYPE(Id, SingletonId)
774#define FLOATING_TYPE(Id, SingletonId)
775#define BUILTIN_TYPE(Id, SingletonId) \
776  case BuiltinType::Id:
777#include "clang/AST/BuiltinTypes.def"
778    // Misc other stuff which doesn't make sense here.
779    return false;
780
781  case BuiltinType::UInt:
782  case BuiltinType::Int:
783  case BuiltinType::Float:
784    LM.setKind(VectorNumElts.isInvalid() ?
785               LengthModifier::None : LengthModifier::AsShortLong);
786    break;
787  case BuiltinType::Double:
788    LM.setKind(VectorNumElts.isInvalid() ?
789               LengthModifier::None : LengthModifier::AsLong);
790    break;
791  case BuiltinType::Char_U:
792  case BuiltinType::UChar:
793  case BuiltinType::Char_S:
794  case BuiltinType::SChar:
795    LM.setKind(LengthModifier::AsChar);
796    break;
797
798  case BuiltinType::Short:
799  case BuiltinType::UShort:
800    LM.setKind(LengthModifier::AsShort);
801    break;
802
803  case BuiltinType::Long:
804  case BuiltinType::ULong:
805    LM.setKind(LengthModifier::AsLong);
806    break;
807
808  case BuiltinType::LongLong:
809  case BuiltinType::ULongLong:
810    LM.setKind(LengthModifier::AsLongLong);
811    break;
812
813  case BuiltinType::LongDouble:
814    LM.setKind(LengthModifier::AsLongDouble);
815    break;
816  }
817
818  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
819  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
820    namedTypeToLengthModifier(QTLM);
821
822  // If fixing the length modifier was enough, we might be done.
823  if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
824    // If we're going to offer a fix anyway, make sure the sign matches.
825    switch (CS.getKind()) {
826    case ConversionSpecifier::uArg:
827    case ConversionSpecifier::UArg:
828      if (QT->isSignedIntegerType())
829        CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
830      break;
831    case ConversionSpecifier::dArg:
832    case ConversionSpecifier::DArg:
833    case ConversionSpecifier::iArg:
834      if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
835        CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
836      break;
837    default:
838      // Other specifiers do not have signed/unsigned variants.
839      break;
840    }
841
842    const analyze_printf::ArgType &ATR = getArgType(CtxIsObjCLiteral);
843    if (ATR.isValid() && ATR.matchesType(CtxQT))
844      return true;
845  }
846
847  // Set conversion specifier and disable any flags which do not apply to it.
848  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
849  if (!isa<TypedefType>(QT) && QT->isCharType()) {
850    CS.setKind(ConversionSpecifier::cArg);
851    LM.setKind(LengthModifier::None);
852    Precision.setHowSpecified(OptionalAmount::NotSpecified);
853    HasAlternativeForm = 0;
854    HasLeadingZeroes = 0;
855    HasPlusPrefix = 0;
856  }
857  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
858  else if (QT->isRealFloatingType()) {
859    CS.setKind(ConversionSpecifier::fArg);
860  }
861  else if (QT->isSignedIntegerType()) {
862    CS.setKind(ConversionSpecifier::dArg);
863    HasAlternativeForm = 0;
864  }
865  else if (QT->isUnsignedIntegerType()) {
866    CS.setKind(ConversionSpecifier::uArg);
867    HasAlternativeForm = 0;
868    HasPlusPrefix = 0;
869  } else {
870    llvm_unreachable("Unexpected type");
871  }
872
873  return true;
874}
875
876void PrintfSpecifier::toString(raw_ostream &osconst {
877  // Whilst some features have no defined order, we are using the order
878  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
879  os << "%";
880
881  // Positional args
882  if (usesPositionalArg()) {
883    os << getPositionalArgIndex() << "$";
884  }
885
886  // Conversion flags
887  if (IsLeftJustified)    os << "-";
888  if (HasPlusPrefix)      os << "+";
889  if (HasSpacePrefix)     os << " ";
890  if (HasAlternativeFormos << "#";
891  if (HasLeadingZeroes)   os << "0";
892
893  // Minimum field width
894  FieldWidth.toString(os);
895  // Precision
896  Precision.toString(os);
897
898  // Vector modifier
899  if (!VectorNumElts.isInvalid())
900    os << 'v' << VectorNumElts.getConstantAmount();
901
902  // Length modifier
903  os << LM.toString();
904  // Conversion specifier
905  os << CS.toString();
906}
907
908bool PrintfSpecifier::hasValidPlusPrefix() const {
909  if (!HasPlusPrefix)
910    return true;
911
912  // The plus prefix only makes sense for signed conversions
913  switch (CS.getKind()) {
914  case ConversionSpecifier::dArg:
915  case ConversionSpecifier::DArg:
916  case ConversionSpecifier::iArg:
917  case ConversionSpecifier::fArg:
918  case ConversionSpecifier::FArg:
919  case ConversionSpecifier::eArg:
920  case ConversionSpecifier::EArg:
921  case ConversionSpecifier::gArg:
922  case ConversionSpecifier::GArg:
923  case ConversionSpecifier::aArg:
924  case ConversionSpecifier::AArg:
925  case ConversionSpecifier::FreeBSDrArg:
926  case ConversionSpecifier::FreeBSDyArg:
927    return true;
928
929  default:
930    return false;
931  }
932}
933
934bool PrintfSpecifier::hasValidAlternativeForm() const {
935  if (!HasAlternativeForm)
936    return true;
937
938  // Alternate form flag only valid with the oxXaAeEfFgG conversions
939  switch (CS.getKind()) {
940  case ConversionSpecifier::oArg:
941  case ConversionSpecifier::OArg:
942  case ConversionSpecifier::xArg:
943  case ConversionSpecifier::XArg:
944  case ConversionSpecifier::aArg:
945  case ConversionSpecifier::AArg:
946  case ConversionSpecifier::eArg:
947  case ConversionSpecifier::EArg:
948  case ConversionSpecifier::fArg:
949  case ConversionSpecifier::FArg:
950  case ConversionSpecifier::gArg:
951  case ConversionSpecifier::GArg:
952  case ConversionSpecifier::FreeBSDrArg:
953  case ConversionSpecifier::FreeBSDyArg:
954    return true;
955
956  default:
957    return false;
958  }
959}
960
961bool PrintfSpecifier::hasValidLeadingZeros() const {
962  if (!HasLeadingZeroes)
963    return true;
964
965  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
966  switch (CS.getKind()) {
967  case ConversionSpecifier::dArg:
968  case ConversionSpecifier::DArg:
969  case ConversionSpecifier::iArg:
970  case ConversionSpecifier::oArg:
971  case ConversionSpecifier::OArg:
972  case ConversionSpecifier::uArg:
973  case ConversionSpecifier::UArg:
974  case ConversionSpecifier::xArg:
975  case ConversionSpecifier::XArg:
976  case ConversionSpecifier::aArg:
977  case ConversionSpecifier::AArg:
978  case ConversionSpecifier::eArg:
979  case ConversionSpecifier::EArg:
980  case ConversionSpecifier::fArg:
981  case ConversionSpecifier::FArg:
982  case ConversionSpecifier::gArg:
983  case ConversionSpecifier::GArg:
984  case ConversionSpecifier::FreeBSDrArg:
985  case ConversionSpecifier::FreeBSDyArg:
986    return true;
987
988  default:
989    return false;
990  }
991}
992
993bool PrintfSpecifier::hasValidSpacePrefix() const {
994  if (!HasSpacePrefix)
995    return true;
996
997  // The space prefix only makes sense for signed conversions
998  switch (CS.getKind()) {
999  case ConversionSpecifier::dArg:
1000  case ConversionSpecifier::DArg:
1001  case ConversionSpecifier::iArg:
1002  case ConversionSpecifier::fArg:
1003  case ConversionSpecifier::FArg:
1004  case ConversionSpecifier::eArg:
1005  case ConversionSpecifier::EArg:
1006  case ConversionSpecifier::gArg:
1007  case ConversionSpecifier::GArg:
1008  case ConversionSpecifier::aArg:
1009  case ConversionSpecifier::AArg:
1010  case ConversionSpecifier::FreeBSDrArg:
1011  case ConversionSpecifier::FreeBSDyArg:
1012    return true;
1013
1014  default:
1015    return false;
1016  }
1017}
1018
1019bool PrintfSpecifier::hasValidLeftJustified() const {
1020  if (!IsLeftJustified)
1021    return true;
1022
1023  // The left justified flag is valid for all conversions except n
1024  switch (CS.getKind()) {
1025  case ConversionSpecifier::nArg:
1026    return false;
1027
1028  default:
1029    return true;
1030  }
1031}
1032
1033bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
1034  if (!HasThousandsGrouping)
1035    return true;
1036
1037  switch (CS.getKind()) {
1038    case ConversionSpecifier::dArg:
1039    case ConversionSpecifier::DArg:
1040    case ConversionSpecifier::iArg:
1041    case ConversionSpecifier::uArg:
1042    case ConversionSpecifier::UArg:
1043    case ConversionSpecifier::fArg:
1044    case ConversionSpecifier::FArg:
1045    case ConversionSpecifier::gArg:
1046    case ConversionSpecifier::GArg:
1047      return true;
1048    default:
1049      return false;
1050  }
1051}
1052
1053bool PrintfSpecifier::hasValidPrecision() const {
1054  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
1055    return true;
1056
1057  // Precision is only valid with the diouxXaAeEfFgGsP conversions
1058  switch (CS.getKind()) {
1059  case ConversionSpecifier::dArg:
1060  case ConversionSpecifier::DArg:
1061  case ConversionSpecifier::iArg:
1062  case ConversionSpecifier::oArg:
1063  case ConversionSpecifier::OArg:
1064  case ConversionSpecifier::uArg:
1065  case ConversionSpecifier::UArg:
1066  case ConversionSpecifier::xArg:
1067  case ConversionSpecifier::XArg:
1068  case ConversionSpecifier::aArg:
1069  case ConversionSpecifier::AArg:
1070  case ConversionSpecifier::eArg:
1071  case ConversionSpecifier::EArg:
1072  case ConversionSpecifier::fArg:
1073  case ConversionSpecifier::FArg:
1074  case ConversionSpecifier::gArg:
1075  case ConversionSpecifier::GArg:
1076  case ConversionSpecifier::sArg:
1077  case ConversionSpecifier::FreeBSDrArg:
1078  case ConversionSpecifier::FreeBSDyArg:
1079  case ConversionSpecifier::PArg:
1080    return true;
1081
1082  default:
1083    return false;
1084  }
1085}
1086bool PrintfSpecifier::hasValidFieldWidth() const {
1087  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1088      return true;
1089
1090  // The field width is valid for all conversions except n
1091  switch (CS.getKind()) {
1092  case ConversionSpecifier::nArg:
1093    return false;
1094
1095  default:
1096    return true;
1097  }
1098}
1099
clang::analyze_printf::PrintfSpecifier::getScalarArgType
clang::analyze_printf::PrintfSpecifier::getArgType
clang::analyze_printf::PrintfSpecifier::fixType
clang::analyze_printf::PrintfSpecifier::toString
clang::analyze_printf::PrintfSpecifier::hasValidPlusPrefix
clang::analyze_printf::PrintfSpecifier::hasValidAlternativeForm
clang::analyze_printf::PrintfSpecifier::hasValidLeadingZeros
clang::analyze_printf::PrintfSpecifier::hasValidSpacePrefix
clang::analyze_printf::PrintfSpecifier::hasValidLeftJustified
clang::analyze_printf::PrintfSpecifier::hasValidThousandsGroupingPrefix
clang::analyze_printf::PrintfSpecifier::hasValidPrecision
clang::analyze_printf::PrintfSpecifier::hasValidFieldWidth