Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//= FormatString.h - Analysis of printf/fprintf 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
// This file defines APIs for analyzing the format strings of printf, fscanf,
10
// and friends.
11
//
12
// The structure of format strings for fprintf are described in C99 7.19.6.1.
13
//
14
// The structure of format strings for fscanf are described in C99 7.19.6.2.
15
//
16
//===----------------------------------------------------------------------===//
17
 
18
#ifndef LLVM_CLANG_AST_FORMATSTRING_H
19
#define LLVM_CLANG_AST_FORMATSTRING_H
20
 
21
#include "clang/AST/CanonicalType.h"
22
#include <optional>
23
 
24
namespace clang {
25
 
26
class TargetInfo;
27
 
28
//===----------------------------------------------------------------------===//
29
/// Common components of both fprintf and fscanf format strings.
30
namespace analyze_format_string {
31
 
32
/// Class representing optional flags with location and representation
33
/// information.
34
class OptionalFlag {
35
public:
36
  OptionalFlag(const char *Representation)
37
      : representation(Representation), flag(false) {}
38
  bool isSet() const { return flag; }
39
  void set() { flag = true; }
40
  void clear() { flag = false; }
41
  void setPosition(const char *position) {
42
    assert(position);
43
    flag = true;
44
    this->position = position;
45
  }
46
  const char *getPosition() const {
47
    assert(position);
48
    return position;
49
  }
50
  const char *toString() const { return representation; }
51
 
52
  // Overloaded operators for bool like qualities
53
  explicit operator bool() const { return flag; }
54
  OptionalFlag& operator=(const bool &rhs) {
55
    flag = rhs;
56
    return *this;  // Return a reference to myself.
57
  }
58
private:
59
  const char *representation;
60
  const char *position;
61
  bool flag;
62
};
63
 
64
/// Represents the length modifier in a format string in scanf/printf.
65
class LengthModifier {
66
public:
67
  enum Kind {
68
    None,
69
    AsChar,       // 'hh'
70
    AsShort,      // 'h'
71
    AsShortLong,  // 'hl' (OpenCL float/int vector element)
72
    AsLong,       // 'l'
73
    AsLongLong,   // 'll'
74
    AsQuad,       // 'q' (BSD, deprecated, for 64-bit integer types)
75
    AsIntMax,     // 'j'
76
    AsSizeT,      // 'z'
77
    AsPtrDiff,    // 't'
78
    AsInt32,      // 'I32' (MSVCRT, like __int32)
79
    AsInt3264,    // 'I'   (MSVCRT, like __int3264 from MIDL)
80
    AsInt64,      // 'I64' (MSVCRT, like __int64)
81
    AsLongDouble, // 'L'
82
    AsAllocate,   // for '%as', GNU extension to C90 scanf
83
    AsMAllocate,  // for '%ms', GNU extension to scanf
84
    AsWide,       // 'w' (MSVCRT, like l but only for c, C, s, S, or Z
85
    AsWideChar = AsLong // for '%ls', only makes sense for printf
86
  };
87
 
88
  LengthModifier()
89
    : Position(nullptr), kind(None) {}
90
  LengthModifier(const char *pos, Kind k)
91
    : Position(pos), kind(k) {}
92
 
93
  const char *getStart() const {
94
    return Position;
95
  }
96
 
97
  unsigned getLength() const {
98
    switch (kind) {
99
      default:
100
        return 1;
101
      case AsLongLong:
102
      case AsChar:
103
        return 2;
104
      case AsInt32:
105
      case AsInt64:
106
        return 3;
107
      case None:
108
        return 0;
109
    }
110
  }
111
 
112
  Kind getKind() const { return kind; }
113
  void setKind(Kind k) { kind = k; }
114
 
115
  const char *toString() const;
116
 
117
private:
118
  const char *Position;
119
  Kind kind;
120
};
121
 
122
class ConversionSpecifier {
123
public:
124
  enum Kind {
125
    InvalidSpecifier = 0,
126
    // C99 conversion specifiers.
127
    cArg,
128
    dArg,
129
    DArg, // Apple extension
130
    iArg,
131
    // C23 conversion specifiers.
132
    bArg,
133
    BArg,
134
 
135
    IntArgBeg = dArg,
136
    IntArgEnd = BArg,
137
 
138
    oArg,
139
    OArg, // Apple extension
140
    uArg,
141
    UArg, // Apple extension
142
    xArg,
143
    XArg,
144
    UIntArgBeg = oArg,
145
    UIntArgEnd = XArg,
146
 
147
    fArg,
148
    FArg,
149
    eArg,
150
    EArg,
151
    gArg,
152
    GArg,
153
    aArg,
154
    AArg,
155
    DoubleArgBeg = fArg,
156
    DoubleArgEnd = AArg,
157
 
158
    sArg,
159
    pArg,
160
    nArg,
161
    PercentArg,
162
    CArg,
163
    SArg,
164
 
165
    // Apple extension: P specifies to os_log that the data being pointed to is
166
    // to be copied by os_log. The precision indicates the number of bytes to
167
    // copy.
168
    PArg,
169
 
170
    // ** Printf-specific **
171
 
172
    ZArg, // MS extension
173
 
174
    // Objective-C specific specifiers.
175
    ObjCObjArg, // '@'
176
    ObjCBeg = ObjCObjArg,
177
    ObjCEnd = ObjCObjArg,
178
 
179
    // FreeBSD kernel specific specifiers.
180
    FreeBSDbArg,
181
    FreeBSDDArg,
182
    FreeBSDrArg,
183
    FreeBSDyArg,
184
 
185
    // GlibC specific specifiers.
186
    PrintErrno, // 'm'
187
 
188
    PrintfConvBeg = ObjCObjArg,
189
    PrintfConvEnd = PrintErrno,
190
 
191
    // ** Scanf-specific **
192
    ScanListArg, // '['
193
    ScanfConvBeg = ScanListArg,
194
    ScanfConvEnd = ScanListArg
195
  };
196
 
197
  ConversionSpecifier(bool isPrintf = true)
198
    : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr),
199
      kind(InvalidSpecifier) {}
200
 
201
  ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
202
    : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {}
203
 
204
  const char *getStart() const {
205
    return Position;
206
  }
207
 
208
  StringRef getCharacters() const {
209
    return StringRef(getStart(), getLength());
210
  }
211
 
212
  bool consumesDataArgument() const {
213
    switch (kind) {
214
      case PrintErrno:
215
        assert(IsPrintf);
216
        return false;
217
      case PercentArg:
218
        return false;
219
      case InvalidSpecifier:
220
        return false;
221
      default:
222
        return true;
223
    }
224
  }
225
 
226
  Kind getKind() const { return kind; }
227
  void setKind(Kind k) { kind = k; }
228
  unsigned getLength() const {
229
    return EndScanList ? EndScanList - Position : 1;
230
  }
231
  void setEndScanList(const char *pos) { EndScanList = pos; }
232
 
233
  bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) ||
234
    kind == FreeBSDrArg || kind == FreeBSDyArg; }
235
  bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
236
  bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; }
237
  bool isDoubleArg() const {
238
    return kind >= DoubleArgBeg && kind <= DoubleArgEnd;
239
  }
240
 
241
  const char *toString() const;
242
 
243
  bool isPrintfKind() const { return IsPrintf; }
244
 
245
  std::optional<ConversionSpecifier> getStandardSpecifier() const;
246
 
247
protected:
248
  bool IsPrintf;
249
  const char *Position;
250
  const char *EndScanList;
251
  Kind kind;
252
};
253
 
254
class ArgType {
255
public:
256
  enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
257
              AnyCharTy, CStrTy, WCStrTy, WIntTy };
258
 
259
  /// How well a given conversion specifier matches its argument.
260
  enum MatchKind {
261
    /// The conversion specifier and the argument types are incompatible. For
262
    /// instance, "%d" and float.
263
    NoMatch = 0,
264
    /// The conversion specifier and the argument type are compatible. For
265
    /// instance, "%d" and int.
266
    Match = 1,
267
    /// The conversion specifier and the argument type are compatible because of
268
    /// default argument promotions. For instance, "%hhd" and int.
269
    MatchPromotion,
270
    /// The conversion specifier and the argument type are compatible but still
271
    /// seems likely to be an error. For instanace, "%hhd" and short.
272
    NoMatchPromotionTypeConfusion,
273
    /// The conversion specifier and the argument type are disallowed by the C
274
    /// standard, but are in practice harmless. For instance, "%p" and int*.
275
    NoMatchPedantic,
276
    /// The conversion specifier and the argument type are compatible, but still
277
    /// seems likely to be an error. For instance, "%hd" and _Bool.
278
    NoMatchTypeConfusion,
279
  };
280
 
281
private:
282
  const Kind K;
283
  QualType T;
284
  const char *Name = nullptr;
285
  bool Ptr = false;
286
 
287
  /// The TypeKind identifies certain well-known types like size_t and
288
  /// ptrdiff_t.
289
  enum class TypeKind { DontCare, SizeT, PtrdiffT };
290
  TypeKind TK = TypeKind::DontCare;
291
 
292
public:
293
  ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {}
294
  ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {}
295
  ArgType(CanQualType T) : K(SpecificTy), T(T) {}
296
 
297
  static ArgType Invalid() { return ArgType(InvalidTy); }
298
  bool isValid() const { return K != InvalidTy; }
299
 
300
  bool isSizeT() const { return TK == TypeKind::SizeT; }
301
 
302
  bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; }
303
 
304
  /// Create an ArgType which corresponds to the type pointer to A.
305
  static ArgType PtrTo(const ArgType& A) {
306
    assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");
307
    ArgType Res = A;
308
    Res.Ptr = true;
309
    return Res;
310
  }
311
 
312
  /// Create an ArgType which corresponds to the size_t/ssize_t type.
313
  static ArgType makeSizeT(const ArgType &A) {
314
    ArgType Res = A;
315
    Res.TK = TypeKind::SizeT;
316
    return Res;
317
  }
318
 
319
  /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t
320
  /// type.
321
  static ArgType makePtrdiffT(const ArgType &A) {
322
    ArgType Res = A;
323
    Res.TK = TypeKind::PtrdiffT;
324
    return Res;
325
  }
326
 
327
  MatchKind matchesType(ASTContext &C, QualType argTy) const;
328
 
329
  QualType getRepresentativeType(ASTContext &C) const;
330
 
331
  ArgType makeVectorType(ASTContext &C, unsigned NumElts) const;
332
 
333
  std::string getRepresentativeTypeName(ASTContext &C) const;
334
};
335
 
336
class OptionalAmount {
337
public:
338
  enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
339
 
340
  OptionalAmount(HowSpecified howSpecified,
341
                 unsigned amount,
342
                 const char *amountStart,
343
                 unsigned amountLength,
344
                 bool usesPositionalArg)
345
  : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
346
  UsesPositionalArg(usesPositionalArg), UsesDotPrefix(false) {}
347
 
348
  OptionalAmount(bool valid = true)
349
  : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
350
  UsesPositionalArg(false), UsesDotPrefix(false) {}
351
 
352
  explicit OptionalAmount(unsigned Amount)
353
    : start(nullptr), length(0), hs(Constant), amt(Amount),
354
    UsesPositionalArg(false), UsesDotPrefix(false) {}
355
 
356
  bool isInvalid() const {
357
    return hs == Invalid;
358
  }
359
 
360
  HowSpecified getHowSpecified() const { return hs; }
361
  void setHowSpecified(HowSpecified h) { hs = h; }
362
 
363
  bool hasDataArgument() const { return hs == Arg; }
364
 
365
  unsigned getArgIndex() const {
366
    assert(hasDataArgument());
367
    return amt;
368
  }
369
 
370
  unsigned getConstantAmount() const {
371
    assert(hs == Constant);
372
    return amt;
373
  }
374
 
375
  const char *getStart() const {
376
      // We include the . character if it is given.
377
    return start - UsesDotPrefix;
378
  }
379
 
380
  unsigned getConstantLength() const {
381
    assert(hs == Constant);
382
    return length + UsesDotPrefix;
383
  }
384
 
385
  ArgType getArgType(ASTContext &Ctx) const;
386
 
387
  void toString(raw_ostream &os) const;
388
 
389
  bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
390
  unsigned getPositionalArgIndex() const {
391
    assert(hasDataArgument());
392
    return amt + 1;
393
  }
394
 
395
  bool usesDotPrefix() const { return UsesDotPrefix; }
396
  void setUsesDotPrefix() { UsesDotPrefix = true; }
397
 
398
private:
399
  const char *start;
400
  unsigned length;
401
  HowSpecified hs;
402
  unsigned amt;
403
  bool UsesPositionalArg : 1;
404
  bool UsesDotPrefix;
405
};
406
 
407
 
408
class FormatSpecifier {
409
protected:
410
  LengthModifier LM;
411
  OptionalAmount FieldWidth;
412
  ConversionSpecifier CS;
413
  OptionalAmount VectorNumElts;
414
 
415
  /// Positional arguments, an IEEE extension:
416
  ///  IEEE Std 1003.1, 2004 Edition
417
  ///  http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
418
  bool UsesPositionalArg;
419
  unsigned argIndex;
420
public:
421
  FormatSpecifier(bool isPrintf)
422
    : CS(isPrintf), VectorNumElts(false),
423
      UsesPositionalArg(false), argIndex(0) {}
424
 
425
  void setLengthModifier(LengthModifier lm) {
426
    LM = lm;
427
  }
428
 
429
  void setUsesPositionalArg() { UsesPositionalArg = true; }
430
 
431
  void setArgIndex(unsigned i) {
432
    argIndex = i;
433
  }
434
 
435
  unsigned getArgIndex() const {
436
    return argIndex;
437
  }
438
 
439
  unsigned getPositionalArgIndex() const {
440
    return argIndex + 1;
441
  }
442
 
443
  const LengthModifier &getLengthModifier() const {
444
    return LM;
445
  }
446
 
447
  const OptionalAmount &getFieldWidth() const {
448
    return FieldWidth;
449
  }
450
 
451
  void setVectorNumElts(const OptionalAmount &Amt) {
452
    VectorNumElts = Amt;
453
  }
454
 
455
  const OptionalAmount &getVectorNumElts() const {
456
    return VectorNumElts;
457
  }
458
 
459
  void setFieldWidth(const OptionalAmount &Amt) {
460
    FieldWidth = Amt;
461
  }
462
 
463
  bool usesPositionalArg() const { return UsesPositionalArg; }
464
 
465
  bool hasValidLengthModifier(const TargetInfo &Target,
466
                              const LangOptions &LO) const;
467
 
468
  bool hasStandardLengthModifier() const;
469
 
470
  std::optional<LengthModifier> getCorrectedLengthModifier() const;
471
 
472
  bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
473
 
474
  bool hasStandardLengthConversionCombination() const;
475
 
476
  /// For a TypedefType QT, if it is a named integer type such as size_t,
477
  /// assign the appropriate value to LM and return true.
478
  static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);
479
};
480
 
481
} // end analyze_format_string namespace
482
 
483
//===----------------------------------------------------------------------===//
484
/// Pieces specific to fprintf format strings.
485
 
486
namespace analyze_printf {
487
 
488
class PrintfConversionSpecifier :
489
  public analyze_format_string::ConversionSpecifier  {
490
public:
491
  PrintfConversionSpecifier()
492
    : ConversionSpecifier(true, nullptr, InvalidSpecifier) {}
493
 
494
  PrintfConversionSpecifier(const char *pos, Kind k)
495
    : ConversionSpecifier(true, pos, k) {}
496
 
497
  bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
498
  bool isDoubleArg() const { return kind >= DoubleArgBeg &&
499
                                    kind <= DoubleArgEnd; }
500
 
501
  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
502
    return CS->isPrintfKind();
503
  }
504
};
505
 
506
using analyze_format_string::ArgType;
507
using analyze_format_string::LengthModifier;
508
using analyze_format_string::OptionalAmount;
509
using analyze_format_string::OptionalFlag;
510
 
511
class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
512
  OptionalFlag HasThousandsGrouping; // ''', POSIX extension.
513
  OptionalFlag IsLeftJustified; // '-'
514
  OptionalFlag HasPlusPrefix; // '+'
515
  OptionalFlag HasSpacePrefix; // ' '
516
  OptionalFlag HasAlternativeForm; // '#'
517
  OptionalFlag HasLeadingZeroes; // '0'
518
  OptionalFlag HasObjCTechnicalTerm; // '[tt]'
519
  OptionalFlag IsPrivate;            // '{private}'
520
  OptionalFlag IsPublic;             // '{public}'
521
  OptionalFlag IsSensitive;          // '{sensitive}'
522
  OptionalAmount Precision;
523
  StringRef MaskType;
524
 
525
  ArgType getScalarArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
526
 
527
public:
528
  PrintfSpecifier()
529
      : FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"),
530
        IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
531
        HasAlternativeForm("#"), HasLeadingZeroes("0"),
532
        HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public"),
533
        IsSensitive("sensitive") {}
534
 
535
  static PrintfSpecifier Parse(const char *beg, const char *end);
536
 
537
    // Methods for incrementally constructing the PrintfSpecifier.
538
  void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
539
    CS = cs;
540
  }
541
  void setHasThousandsGrouping(const char *position) {
542
    HasThousandsGrouping.setPosition(position);
543
  }
544
  void setIsLeftJustified(const char *position) {
545
    IsLeftJustified.setPosition(position);
546
  }
547
  void setHasPlusPrefix(const char *position) {
548
    HasPlusPrefix.setPosition(position);
549
  }
550
  void setHasSpacePrefix(const char *position) {
551
    HasSpacePrefix.setPosition(position);
552
  }
553
  void setHasAlternativeForm(const char *position) {
554
    HasAlternativeForm.setPosition(position);
555
  }
556
  void setHasLeadingZeros(const char *position) {
557
    HasLeadingZeroes.setPosition(position);
558
  }
559
  void setHasObjCTechnicalTerm(const char *position) {
560
    HasObjCTechnicalTerm.setPosition(position);
561
  }
562
  void setIsPrivate(const char *position) { IsPrivate.setPosition(position); }
563
  void setIsPublic(const char *position) { IsPublic.setPosition(position); }
564
  void setIsSensitive(const char *position) {
565
    IsSensitive.setPosition(position);
566
  }
567
  void setUsesPositionalArg() { UsesPositionalArg = true; }
568
 
569
    // Methods for querying the format specifier.
570
 
571
  const PrintfConversionSpecifier &getConversionSpecifier() const {
572
    return cast<PrintfConversionSpecifier>(CS);
573
  }
574
 
575
  void setPrecision(const OptionalAmount &Amt) {
576
    Precision = Amt;
577
    Precision.setUsesDotPrefix();
578
  }
579
 
580
  const OptionalAmount &getPrecision() const {
581
    return Precision;
582
  }
583
 
584
  bool consumesDataArgument() const {
585
    return getConversionSpecifier().consumesDataArgument();
586
  }
587
 
588
  /// Returns the builtin type that a data argument
589
  /// paired with this format specifier should have.  This method
590
  /// will return null if the format specifier does not have
591
  /// a matching data argument or the matching argument matches
592
  /// more than one type.
593
  ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
594
 
595
  const OptionalFlag &hasThousandsGrouping() const {
596
      return HasThousandsGrouping;
597
  }
598
  const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
599
  const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
600
  const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
601
  const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
602
  const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
603
  const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; }
604
  const OptionalFlag &isPrivate() const { return IsPrivate; }
605
  const OptionalFlag &isPublic() const { return IsPublic; }
606
  const OptionalFlag &isSensitive() const { return IsSensitive; }
607
  bool usesPositionalArg() const { return UsesPositionalArg; }
608
 
609
  StringRef getMaskType() const { return MaskType; }
610
  void setMaskType(StringRef S) { MaskType = S; }
611
 
612
  /// Changes the specifier and length according to a QualType, retaining any
613
  /// flags or options. Returns true on success, or false when a conversion
614
  /// was not successful.
615
  bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx,
616
               bool IsObjCLiteral);
617
 
618
  void toString(raw_ostream &os) const;
619
 
620
  // Validation methods - to check if any element results in undefined behavior
621
  bool hasValidPlusPrefix() const;
622
  bool hasValidAlternativeForm() const;
623
  bool hasValidLeadingZeros() const;
624
  bool hasValidSpacePrefix() const;
625
  bool hasValidLeftJustified() const;
626
  bool hasValidThousandsGroupingPrefix() const;
627
 
628
  bool hasValidPrecision() const;
629
  bool hasValidFieldWidth() const;
630
};
631
}  // end analyze_printf namespace
632
 
633
//===----------------------------------------------------------------------===//
634
/// Pieces specific to fscanf format strings.
635
 
636
namespace analyze_scanf {
637
 
638
class ScanfConversionSpecifier :
639
    public analyze_format_string::ConversionSpecifier  {
640
public:
641
  ScanfConversionSpecifier()
642
    : ConversionSpecifier(false, nullptr, InvalidSpecifier) {}
643
 
644
  ScanfConversionSpecifier(const char *pos, Kind k)
645
    : ConversionSpecifier(false, pos, k) {}
646
 
647
  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
648
    return !CS->isPrintfKind();
649
  }
650
};
651
 
652
using analyze_format_string::ArgType;
653
using analyze_format_string::LengthModifier;
654
using analyze_format_string::OptionalAmount;
655
using analyze_format_string::OptionalFlag;
656
 
657
class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
658
  OptionalFlag SuppressAssignment; // '*'
659
public:
660
  ScanfSpecifier() :
661
    FormatSpecifier(/* isPrintf = */ false),
662
    SuppressAssignment("*") {}
663
 
664
  void setSuppressAssignment(const char *position) {
665
    SuppressAssignment.setPosition(position);
666
  }
667
 
668
  const OptionalFlag &getSuppressAssignment() const {
669
    return SuppressAssignment;
670
  }
671
 
672
  void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
673
    CS = cs;
674
  }
675
 
676
  const ScanfConversionSpecifier &getConversionSpecifier() const {
677
    return cast<ScanfConversionSpecifier>(CS);
678
  }
679
 
680
  bool consumesDataArgument() const {
681
    return CS.consumesDataArgument() && !SuppressAssignment;
682
  }
683
 
684
  ArgType getArgType(ASTContext &Ctx) const;
685
 
686
  bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt,
687
               ASTContext &Ctx);
688
 
689
  void toString(raw_ostream &os) const;
690
 
691
  static ScanfSpecifier Parse(const char *beg, const char *end);
692
};
693
 
694
} // end analyze_scanf namespace
695
 
696
//===----------------------------------------------------------------------===//
697
// Parsing and processing of format strings (both fprintf and fscanf).
698
 
699
namespace analyze_format_string {
700
 
701
enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
702
 
703
class FormatStringHandler {
704
public:
705
  FormatStringHandler() {}
706
  virtual ~FormatStringHandler();
707
 
708
  virtual void HandleNullChar(const char *nullCharacter) {}
709
 
710
  virtual void HandlePosition(const char *startPos, unsigned posLen) {}
711
 
712
  virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
713
                                     PositionContext p) {}
714
 
715
  virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
716
 
717
  virtual void HandleIncompleteSpecifier(const char *startSpecifier,
718
                                         unsigned specifierLen) {}
719
 
720
  virtual void HandleEmptyObjCModifierFlag(const char *startFlags,
721
                                           unsigned flagsLen) {}
722
 
723
  virtual void HandleInvalidObjCModifierFlag(const char *startFlag,
724
                                             unsigned flagLen) {}
725
 
726
  virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,
727
                                            const char *flagsEnd,
728
                                            const char *conversionPosition) {}
729
  // Printf-specific handlers.
730
 
731
  virtual bool HandleInvalidPrintfConversionSpecifier(
732
                                      const analyze_printf::PrintfSpecifier &FS,
733
                                      const char *startSpecifier,
734
                                      unsigned specifierLen) {
735
    return true;
736
  }
737
 
738
  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
739
                                     const char *startSpecifier,
740
                                     unsigned specifierLen,
741
                                     const TargetInfo &Target) {
742
    return true;
743
  }
744
 
745
  /// Handle mask types whose sizes are not between one and eight bytes.
746
  virtual void handleInvalidMaskType(StringRef MaskType) {}
747
 
748
    // Scanf-specific handlers.
749
 
750
  virtual bool HandleInvalidScanfConversionSpecifier(
751
                                        const analyze_scanf::ScanfSpecifier &FS,
752
                                        const char *startSpecifier,
753
                                        unsigned specifierLen) {
754
    return true;
755
  }
756
 
757
  virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
758
                                    const char *startSpecifier,
759
                                    unsigned specifierLen) {
760
    return true;
761
  }
762
 
763
  virtual void HandleIncompleteScanList(const char *start, const char *end) {}
764
};
765
 
766
bool ParsePrintfString(FormatStringHandler &H,
767
                       const char *beg, const char *end, const LangOptions &LO,
768
                       const TargetInfo &Target, bool isFreeBSDKPrintf);
769
 
770
bool ParseFormatStringHasSArg(const char *beg, const char *end,
771
                              const LangOptions &LO, const TargetInfo &Target);
772
 
773
bool ParseScanfString(FormatStringHandler &H,
774
                      const char *beg, const char *end, const LangOptions &LO,
775
                      const TargetInfo &Target);
776
 
777
/// Return true if the given string has at least one formatting specifier.
778
bool parseFormatStringHasFormattingSpecifiers(const char *Begin,
779
                                              const char *End,
780
                                              const LangOptions &LO,
781
                                              const TargetInfo &Target);
782
 
783
} // end analyze_format_string namespace
784
} // end clang namespace
785
#endif