Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/AST/ScanfFormatString.cpp
Line
Count
Source (jump to first uncovered line)
1
//= ScanfFormatString.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 scanf and friends.  The structure of format
10
// strings for fscanf() are described in C99 7.19.6.2.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/AST/FormatString.h"
15
#include "FormatStringParsing.h"
16
#include "clang/Basic/TargetInfo.h"
17
18
using clang::analyze_format_string::ArgType;
19
using clang::analyze_format_string::FormatStringHandler;
20
using clang::analyze_format_string::LengthModifier;
21
using clang::analyze_format_string::OptionalAmount;
22
using clang::analyze_format_string::ConversionSpecifier;
23
using clang::analyze_scanf::ScanfConversionSpecifier;
24
using clang::analyze_scanf::ScanfSpecifier;
25
using clang::UpdateOnReturn;
26
using namespace clang;
27
28
typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
29
        ScanfSpecifierResult;
30
31
static bool ParseScanList(FormatStringHandler &H,
32
                          ScanfConversionSpecifier &CS,
33
75
                          const char *&Beg, const char *E) {
34
75
  const char *I = Beg;
35
75
  const char *start = I - 1;
36
75
  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
37
75
38
75
  // No more characters?
39
75
  if (I == E) {
40
4
    H.HandleIncompleteScanList(start, I);
41
4
    return true;
42
4
  }
43
71
44
71
  // Special case: ']' is the first character.
45
71
  if (*I == ']') {
46
2
    if (++I == E) {
47
0
      H.HandleIncompleteScanList(start, I - 1);
48
0
      return true;
49
0
    }
50
71
  }
51
71
52
71
  // Special case: "^]" are the first characters.
53
71
  if (I + 1 != E && I[0] == '^' && 
I[1] == ']'45
) {
54
2
    I += 2;
55
2
    if (I == E) {
56
0
      H.HandleIncompleteScanList(start, I - 1);
57
0
      return true;
58
0
    }
59
71
  }
60
71
61
71
  // Look for a ']' character which denotes the end of the scan list.
62
241
  
while (71
*I != ']') {
63
178
    if (++I == E) {
64
8
      H.HandleIncompleteScanList(start, I - 1);
65
8
      return true;
66
8
    }
67
178
  }
68
71
69
71
  CS.setEndScanList(I);
70
63
  return false;
71
71
}
72
73
// FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
74
// We can possibly refactor.
75
static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
76
                                                const char *&Beg,
77
                                                const char *E,
78
                                                unsigned &argIndex,
79
                                                const LangOptions &LO,
80
2.00k
                                                const TargetInfo &Target) {
81
2.00k
  using namespace clang::analyze_format_string;
82
2.00k
  using namespace clang::analyze_scanf;
83
2.00k
  const char *I = Beg;
84
2.00k
  const char *Start = nullptr;
85
2.00k
  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
86
2.00k
87
2.00k
    // Look for a '%' character that indicates the start of a format specifier.
88
3.40k
  for ( ; I != E ; 
++I1.40k
) {
89
3.01k
    char c = *I;
90
3.01k
    if (c == '\0') {
91
0
        // Detect spurious null characters, which are likely errors.
92
0
      H.HandleNullChar(I);
93
0
      return true;
94
0
    }
95
3.01k
    if (c == '%') {
96
1.61k
      Start = I++;  // Record the start of the format specifier.
97
1.61k
      break;
98
1.61k
    }
99
3.01k
  }
100
2.00k
101
2.00k
    // No format specifier found?
102
2.00k
  if (!Start)
103
390
    return false;
104
1.61k
105
1.61k
  if (I == E) {
106
0
      // No more characters left?
107
0
    H.HandleIncompleteSpecifier(Start, E - Start);
108
0
    return true;
109
0
  }
110
1.61k
111
1.61k
  ScanfSpecifier FS;
112
1.61k
  if (ParseArgPosition(H, FS, Start, I, E))
113
0
    return true;
114
1.61k
115
1.61k
  if (I == E) {
116
0
      // No more characters left?
117
0
    H.HandleIncompleteSpecifier(Start, E - Start);
118
0
    return true;
119
0
  }
120
1.61k
121
1.61k
  // Look for '*' flag if it is present.
122
1.61k
  if (*I == '*') {
123
33
    FS.setSuppressAssignment(I);
124
33
    if (++I == E) {
125
0
      H.HandleIncompleteSpecifier(Start, E - Start);
126
0
      return true;
127
0
    }
128
1.61k
  }
129
1.61k
130
1.61k
  // Look for the field width (if any).  Unlike printf, this is either
131
1.61k
  // a fixed integer or isn't present.
132
1.61k
  const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
133
1.61k
  if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
134
38
    assert(Amt.getHowSpecified() == OptionalAmount::Constant);
135
38
    FS.setFieldWidth(Amt);
136
38
137
38
    if (I == E) {
138
0
      // No more characters left?
139
0
      H.HandleIncompleteSpecifier(Start, E - Start);
140
0
      return true;
141
0
    }
142
1.61k
  }
143
1.61k
144
1.61k
  // Look for the length modifier.
145
1.61k
  if (ParseLengthModifier(FS, I, E, LO, /*IsScanf=*/true) && 
I == E331
) {
146
0
      // No more characters left?
147
0
    H.HandleIncompleteSpecifier(Start, E - Start);
148
0
    return true;
149
0
  }
150
1.61k
151
1.61k
  // Detect spurious null characters, which are likely errors.
152
1.61k
  if (*I == '\0') {
153
0
    H.HandleNullChar(I);
154
0
    return true;
155
0
  }
156
1.61k
157
1.61k
  // Finally, look for the conversion specifier.
158
1.61k
  const char *conversionPosition = I++;
159
1.61k
  ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
160
1.61k
  switch (*conversionPosition) {
161
1.61k
    default:
162
12
      break;
163
1.61k
    
case '%': k = ConversionSpecifier::PercentArg; break8
;
164
1.61k
    
case 'A': k = ConversionSpecifier::AArg; break2
;
165
1.61k
    
case 'E': k = ConversionSpecifier::EArg; break2
;
166
1.61k
    
case 'F': k = ConversionSpecifier::FArg; break2
;
167
1.61k
    
case 'G': k = ConversionSpecifier::GArg; break2
;
168
1.61k
    
case 'X': k = ConversionSpecifier::XArg; break2
;
169
1.61k
    
case 'a': k = ConversionSpecifier::aArg; break19
;
170
1.61k
    
case 'd': k = ConversionSpecifier::dArg; break741
;
171
1.61k
    
case 'e': k = ConversionSpecifier::eArg; break15
;
172
1.61k
    
case 'f': k = ConversionSpecifier::fArg; break126
;
173
1.61k
    
case 'g': k = ConversionSpecifier::gArg; break8
;
174
1.61k
    
case 'i': k = ConversionSpecifier::iArg; break2
;
175
1.61k
    
case 'n': k = ConversionSpecifier::nArg; break60
;
176
1.61k
    
case 'c': k = ConversionSpecifier::cArg; break42
;
177
1.61k
    
case 'C': k = ConversionSpecifier::CArg; break10
;
178
1.61k
    
case 'S': k = ConversionSpecifier::SArg; break11
;
179
1.61k
    
case '[': k = ConversionSpecifier::ScanListArg; break75
;
180
1.61k
    
case 'u': k = ConversionSpecifier::uArg; break68
;
181
1.61k
    
case 'x': k = ConversionSpecifier::xArg; break22
;
182
1.61k
    
case 'o': k = ConversionSpecifier::oArg; break8
;
183
1.61k
    
case 's': k = ConversionSpecifier::sArg; break352
;
184
1.61k
    
case 'p': k = ConversionSpecifier::pArg; break10
;
185
1.61k
    // Apple extensions
186
1.61k
      // Apple-specific
187
1.61k
    case 'D':
188
4
      if (Target.getTriple().isOSDarwin())
189
4
        k = ConversionSpecifier::DArg;
190
4
      break;
191
1.61k
    case 'O':
192
4
      if (Target.getTriple().isOSDarwin())
193
4
        k = ConversionSpecifier::OArg;
194
4
      break;
195
1.61k
    case 'U':
196
4
      if (Target.getTriple().isOSDarwin())
197
4
        k = ConversionSpecifier::UArg;
198
4
      break;
199
1.61k
  }
200
1.61k
  ScanfConversionSpecifier CS(conversionPosition, k);
201
1.61k
  if (k == ScanfConversionSpecifier::ScanListArg) {
202
75
    if (ParseScanList(H, CS, I, E))
203
12
      return true;
204
1.59k
  }
205
1.59k
  FS.setConversionSpecifier(CS);
206
1.59k
  if (CS.consumesDataArgument() && 
!FS.getSuppressAssignment()1.57k
207
1.59k
      && 
!FS.usesPositionalArg()1.54k
)
208
1.53k
    FS.setArgIndex(argIndex++);
209
1.59k
210
1.59k
  // FIXME: '%' and '*' doesn't make sense.  Issue a warning.
211
1.59k
  // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
212
1.59k
213
1.59k
  if (k == ScanfConversionSpecifier::InvalidSpecifier) {
214
12
    unsigned Len = I - Beg;
215
12
    if (ParseUTF8InvalidSpecifier(Beg, E, Len)) {
216
4
      CS.setEndScanList(Beg + Len);
217
4
      FS.setConversionSpecifier(CS);
218
4
    }
219
12
    // Assume the conversion takes one argument.
220
12
    return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len);
221
12
  }
222
1.58k
  return ScanfSpecifierResult(Start, FS);
223
1.58k
}
224
225
1.60k
ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
226
1.60k
  const ScanfConversionSpecifier &CS = getConversionSpecifier();
227
1.60k
228
1.60k
  if (!CS.consumesDataArgument())
229
0
    return ArgType::Invalid();
230
1.60k
231
1.60k
  switch(CS.getKind()) {
232
1.60k
    // Signed int.
233
1.60k
    case ConversionSpecifier::dArg:
234
756
    case ConversionSpecifier::DArg:
235
756
    case ConversionSpecifier::iArg:
236
756
      switch (LM.getKind()) {
237
756
        case LengthModifier::None:
238
684
          return ArgType::PtrTo(Ctx.IntTy);
239
756
        case LengthModifier::AsChar:
240
0
          return ArgType::PtrTo(ArgType::AnyCharTy);
241
756
        case LengthModifier::AsShort:
242
3
          return ArgType::PtrTo(Ctx.ShortTy);
243
756
        case LengthModifier::AsLong:
244
39
          return ArgType::PtrTo(Ctx.LongTy);
245
756
        case LengthModifier::AsLongLong:
246
7
        case LengthModifier::AsQuad:
247
7
          return ArgType::PtrTo(Ctx.LongLongTy);
248
7
        case LengthModifier::AsInt64:
249
0
          return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
250
7
        case LengthModifier::AsIntMax:
251
3
          return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
252
7
        case LengthModifier::AsSizeT:
253
7
          return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
254
7
        case LengthModifier::AsPtrDiff:
255
7
          return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
256
7
        case LengthModifier::AsLongDouble:
257
4
          // GNU extension.
258
4
          return ArgType::PtrTo(Ctx.LongLongTy);
259
7
        case LengthModifier::AsAllocate:
260
2
        case LengthModifier::AsMAllocate:
261
2
        case LengthModifier::AsInt32:
262
2
        case LengthModifier::AsInt3264:
263
2
        case LengthModifier::AsWide:
264
2
        case LengthModifier::AsShortLong:
265
2
          return ArgType::Invalid();
266
0
      }
267
0
      llvm_unreachable("Unsupported LengthModifier Type");
268
0
269
0
    // Unsigned int.
270
115
    case ConversionSpecifier::oArg:
271
115
    case ConversionSpecifier::OArg:
272
115
    case ConversionSpecifier::uArg:
273
115
    case ConversionSpecifier::UArg:
274
115
    case ConversionSpecifier::xArg:
275
115
    case ConversionSpecifier::XArg:
276
115
      switch (LM.getKind()) {
277
115
        case LengthModifier::None:
278
39
          return ArgType::PtrTo(Ctx.UnsignedIntTy);
279
115
        case LengthModifier::AsChar:
280
2
          return ArgType::PtrTo(Ctx.UnsignedCharTy);
281
115
        case LengthModifier::AsShort:
282
13
          return ArgType::PtrTo(Ctx.UnsignedShortTy);
283
115
        case LengthModifier::AsLong:
284
38
          return ArgType::PtrTo(Ctx.UnsignedLongTy);
285
115
        case LengthModifier::AsLongLong:
286
1
        case LengthModifier::AsQuad:
287
1
          return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
288
1
        case LengthModifier::AsInt64:
289
0
          return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
290
3
        case LengthModifier::AsIntMax:
291
3
          return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
292
7
        case LengthModifier::AsSizeT:
293
7
          return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
294
4
        case LengthModifier::AsPtrDiff:
295
4
          return ArgType::PtrTo(
296
4
              ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
297
8
        case LengthModifier::AsLongDouble:
298
8
          // GNU extension.
299
8
          return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
300
1
        case LengthModifier::AsAllocate:
301
0
        case LengthModifier::AsMAllocate:
302
0
        case LengthModifier::AsInt32:
303
0
        case LengthModifier::AsInt3264:
304
0
        case LengthModifier::AsWide:
305
0
        case LengthModifier::AsShortLong:
306
0
          return ArgType::Invalid();
307
0
      }
308
0
      llvm_unreachable("Unsupported LengthModifier Type");
309
0
310
0
    // Float.
311
190
    case ConversionSpecifier::aArg:
312
190
    case ConversionSpecifier::AArg:
313
190
    case ConversionSpecifier::eArg:
314
190
    case ConversionSpecifier::EArg:
315
190
    case ConversionSpecifier::fArg:
316
190
    case ConversionSpecifier::FArg:
317
190
    case ConversionSpecifier::gArg:
318
190
    case ConversionSpecifier::GArg:
319
190
      switch (LM.getKind()) {
320
190
        case LengthModifier::None:
321
82
          return ArgType::PtrTo(Ctx.FloatTy);
322
190
        case LengthModifier::AsLong:
323
92
          return ArgType::PtrTo(Ctx.DoubleTy);
324
190
        case LengthModifier::AsLongDouble:
325
16
          return ArgType::PtrTo(Ctx.LongDoubleTy);
326
190
        default:
327
0
          return ArgType::Invalid();
328
0
      }
329
0
330
0
    // Char, string and scanlist.
331
449
    case ConversionSpecifier::cArg:
332
449
    case ConversionSpecifier::sArg:
333
449
    case ConversionSpecifier::ScanListArg:
334
449
      switch (LM.getKind()) {
335
449
        case LengthModifier::None:
336
405
          return ArgType::PtrTo(ArgType::AnyCharTy);
337
449
        case LengthModifier::AsLong:
338
16
        case LengthModifier::AsWide:
339
16
          return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
340
18
        case LengthModifier::AsAllocate:
341
18
        case LengthModifier::AsMAllocate:
342
18
          return ArgType::PtrTo(ArgType::CStrTy);
343
18
        case LengthModifier::AsShort:
344
4
          if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
345
2
            return ArgType::PtrTo(ArgType::AnyCharTy);
346
2
          LLVM_FALLTHROUGH;
347
8
        default:
348
8
          return ArgType::Invalid();
349
0
      }
350
26
    case ConversionSpecifier::CArg:
351
26
    case ConversionSpecifier::SArg:
352
26
      // FIXME: Mac OS X specific?
353
26
      switch (LM.getKind()) {
354
26
        case LengthModifier::None:
355
15
        case LengthModifier::AsWide:
356
15
          return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
357
15
        case LengthModifier::AsAllocate:
358
9
        case LengthModifier::AsMAllocate:
359
9
          return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));
360
9
        case LengthModifier::AsShort:
361
2
          if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
362
2
            return ArgType::PtrTo(ArgType::AnyCharTy);
363
0
          LLVM_FALLTHROUGH;
364
0
        default:
365
0
          return ArgType::Invalid();
366
0
      }
367
0
368
0
    // Pointer.
369
11
    case ConversionSpecifier::pArg:
370
11
      return ArgType::PtrTo(ArgType::CPointerTy);
371
0
372
0
    // Write-back.
373
60
    case ConversionSpecifier::nArg:
374
60
      switch (LM.getKind()) {
375
60
        case LengthModifier::None:
376
20
          return ArgType::PtrTo(Ctx.IntTy);
377
60
        case LengthModifier::AsChar:
378
8
          return ArgType::PtrTo(Ctx.SignedCharTy);
379
60
        case LengthModifier::AsShort:
380
6
          return ArgType::PtrTo(Ctx.ShortTy);
381
60
        case LengthModifier::AsLong:
382
6
          return ArgType::PtrTo(Ctx.LongTy);
383
60
        case LengthModifier::AsLongLong:
384
12
        case LengthModifier::AsQuad:
385
12
          return ArgType::PtrTo(Ctx.LongLongTy);
386
12
        case LengthModifier::AsInt64:
387
0
          return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
388
12
        case LengthModifier::AsIntMax:
389
0
          return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
390
12
        case LengthModifier::AsSizeT:
391
4
          return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
392
12
        case LengthModifier::AsPtrDiff:
393
4
          return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
394
12
        case LengthModifier::AsLongDouble:
395
0
          return ArgType(); // FIXME: Is this a known extension?
396
12
        case LengthModifier::AsAllocate:
397
0
        case LengthModifier::AsMAllocate:
398
0
        case LengthModifier::AsInt32:
399
0
        case LengthModifier::AsInt3264:
400
0
        case LengthModifier::AsWide:
401
0
        case LengthModifier::AsShortLong:
402
0
          return ArgType::Invalid();
403
0
        }
404
0
405
0
    default:
406
0
      break;
407
0
  }
408
0
409
0
  return ArgType();
410
0
}
411
412
bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
413
                             const LangOptions &LangOpt,
414
149
                             ASTContext &Ctx) {
415
149
416
149
  // %n is different from other conversion specifiers; don't try to fix it.
417
149
  if (CS.getKind() == ConversionSpecifier::nArg)
418
20
    return false;
419
129
420
129
  if (!QT->isPointerType())
421
10
    return false;
422
119
423
119
  QualType PT = QT->getPointeeType();
424
119
425
119
  // If it's an enum, get its underlying type.
426
119
  if (const EnumType *ETy = PT->getAs<EnumType>()) {
427
6
    // Don't try to fix incomplete enums.
428
6
    if (!ETy->getDecl()->isComplete())
429
6
      return false;
430
0
    PT = ETy->getDecl()->getIntegerType();
431
0
  }
432
119
433
119
  const BuiltinType *BT = PT->getAs<BuiltinType>();
434
113
  if (!BT)
435
16
    return false;
436
97
437
97
  // Pointer to a character.
438
97
  if (PT->isAnyCharacterType()) {
439
8
    CS.setKind(ConversionSpecifier::sArg);
440
8
    if (PT->isWideCharType())
441
0
      LM.setKind(LengthModifier::AsWideChar);
442
8
    else
443
8
      LM.setKind(LengthModifier::None);
444
8
445
8
    // If we know the target array length, we can use it as a field width.
446
8
    if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
447
3
      if (CAT->getSizeModifier() == ArrayType::Normal)
448
3
        FieldWidth = OptionalAmount(OptionalAmount::Constant,
449
3
                                    CAT->getSize().getZExtValue() - 1,
450
3
                                    "", 0, false);
451
3
452
3
    }
453
8
    return true;
454
8
  }
455
89
456
89
  // Figure out the length modifier.
457
89
  switch (BT->getKind()) {
458
89
    // no modifier
459
89
    case BuiltinType::UInt:
460
39
    case BuiltinType::Int:
461
39
    case BuiltinType::Float:
462
39
      LM.setKind(LengthModifier::None);
463
39
      break;
464
39
465
39
    // hh
466
39
    case BuiltinType::Char_U:
467
0
    case BuiltinType::UChar:
468
0
    case BuiltinType::Char_S:
469
0
    case BuiltinType::SChar:
470
0
      LM.setKind(LengthModifier::AsChar);
471
0
      break;
472
0
473
0
    // h
474
2
    case BuiltinType::Short:
475
2
    case BuiltinType::UShort:
476
2
      LM.setKind(LengthModifier::AsShort);
477
2
      break;
478
2
479
2
    // l
480
36
    case BuiltinType::Long:
481
36
    case BuiltinType::ULong:
482
36
    case BuiltinType::Double:
483
36
      LM.setKind(LengthModifier::AsLong);
484
36
      break;
485
36
486
36
    // ll
487
36
    case BuiltinType::LongLong:
488
2
    case BuiltinType::ULongLong:
489
2
      LM.setKind(LengthModifier::AsLongLong);
490
2
      break;
491
2
492
2
    // L
493
8
    case BuiltinType::LongDouble:
494
8
      LM.setKind(LengthModifier::AsLongDouble);
495
8
      break;
496
2
497
2
    // Don't know.
498
2
    default:
499
2
      return false;
500
87
  }
501
87
502
87
  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
503
87
  if (isa<TypedefType>(PT) && 
(10
LangOpt.C9910
||
LangOpt.CPlusPlus110
))
504
10
    namedTypeToLengthModifier(PT, LM);
505
87
506
87
  // If fixing the length modifier was enough, we are done.
507
87
  if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
508
67
    const analyze_scanf::ArgType &AT = getArgType(Ctx);
509
67
    if (AT.isValid() && AT.matchesType(Ctx, QT))
510
22
      return true;
511
65
  }
512
65
513
65
  // Figure out the conversion specifier.
514
65
  if (PT->isRealFloatingType())
515
33
    CS.setKind(ConversionSpecifier::fArg);
516
32
  else if (PT->isSignedIntegerType())
517
24
    CS.setKind(ConversionSpecifier::dArg);
518
8
  else if (PT->isUnsignedIntegerType())
519
8
    CS.setKind(ConversionSpecifier::uArg);
520
8
  else
521
8
    
llvm_unreachable0
("Unexpected type");
522
65
523
65
  return true;
524
65
}
525
526
95
void ScanfSpecifier::toString(raw_ostream &os) const {
527
95
  os << "%";
528
95
529
95
  if (usesPositionalArg())
530
0
    os << getPositionalArgIndex() << "$";
531
95
  if (SuppressAssignment)
532
0
    os << "*";
533
95
534
95
  FieldWidth.toString(os);
535
95
  os << LM.toString();
536
95
  os << CS.toString();
537
95
}
538
539
bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
540
                                                    const char *I,
541
                                                    const char *E,
542
                                                    const LangOptions &LO,
543
1.26k
                                                    const TargetInfo &Target) {
544
1.26k
545
1.26k
  unsigned argIndex = 0;
546
1.26k
547
1.26k
  // Keep looking for a format specifier until we have exhausted the string.
548
3.24k
  while (I != E) {
549
2.00k
    const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
550
2.00k
                                                          LO, Target);
551
2.00k
    // Did a fail-stop error of any kind occur when parsing the specifier?
552
2.00k
    // If so, don't do any more processing.
553
2.00k
    if (FSR.shouldStop())
554
12
      return true;
555
1.98k
      // Did we exhaust the string or encounter an error that
556
1.98k
      // we can recover from?
557
1.98k
    if (!FSR.hasValue())
558
402
      continue;
559
1.58k
      // We have a format specifier.  Pass it to the callback.
560
1.58k
    if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
561
1.58k
                                I - FSR.getStart())) {
562
6
      return true;
563
6
    }
564
1.58k
  }
565
1.26k
  assert(I == E && "Format string not exhausted");
566
1.24k
  return false;
567
1.26k
}