Coverage Report

Created: 2020-09-19 12:23

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