1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H |
19 | #define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H |
20 | |
21 | #include "clang/AST/CanonicalType.h" |
22 | |
23 | namespace clang { |
24 | |
25 | class TargetInfo; |
26 | |
27 | |
28 | |
29 | namespace analyze_format_string { |
30 | |
31 | |
32 | |
33 | class OptionalFlag { |
34 | public: |
35 | OptionalFlag(const char *Representation) |
36 | : representation(Representation), flag(false) {} |
37 | bool isSet() const { return flag; } |
38 | void set() { flag = true; } |
39 | void clear() { flag = false; } |
40 | void setPosition(const char *position) { |
41 | assert(position); |
42 | flag = true; |
43 | this->position = position; |
44 | } |
45 | const char *getPosition() const { |
46 | assert(position); |
47 | return position; |
48 | } |
49 | const char *toString() const { return representation; } |
50 | |
51 | |
52 | explicit operator bool() const { return flag; } |
53 | OptionalFlag& operator=(const bool &rhs) { |
54 | flag = rhs; |
55 | return *this; |
56 | } |
57 | private: |
58 | const char *representation; |
59 | const char *position; |
60 | bool flag; |
61 | }; |
62 | |
63 | |
64 | class LengthModifier { |
65 | public: |
66 | enum Kind { |
67 | None, |
68 | AsChar, |
69 | AsShort, |
70 | AsShortLong, |
71 | AsLong, |
72 | AsLongLong, |
73 | AsQuad, |
74 | AsIntMax, |
75 | AsSizeT, |
76 | AsPtrDiff, |
77 | AsInt32, |
78 | AsInt3264, |
79 | AsInt64, |
80 | AsLongDouble, |
81 | AsAllocate, |
82 | AsMAllocate, |
83 | AsWide, |
84 | AsWideChar = AsLong |
85 | }; |
86 | |
87 | LengthModifier() |
88 | : Position(nullptr), kind(None) {} |
89 | LengthModifier(const char *pos, Kind k) |
90 | : Position(pos), kind(k) {} |
91 | |
92 | const char *getStart() const { |
93 | return Position; |
94 | } |
95 | |
96 | unsigned getLength() const { |
97 | switch (kind) { |
98 | default: |
99 | return 1; |
100 | case AsLongLong: |
101 | case AsChar: |
102 | return 2; |
103 | case AsInt32: |
104 | case AsInt64: |
105 | return 3; |
106 | case None: |
107 | return 0; |
108 | } |
109 | } |
110 | |
111 | Kind getKind() const { return kind; } |
112 | void setKind(Kind k) { kind = k; } |
113 | |
114 | const char *toString() const; |
115 | |
116 | private: |
117 | const char *Position; |
118 | Kind kind; |
119 | }; |
120 | |
121 | class ConversionSpecifier { |
122 | public: |
123 | enum Kind { |
124 | InvalidSpecifier = 0, |
125 | |
126 | cArg, |
127 | dArg, |
128 | DArg, |
129 | iArg, |
130 | IntArgBeg = dArg, |
131 | IntArgEnd = iArg, |
132 | |
133 | oArg, |
134 | OArg, |
135 | uArg, |
136 | UArg, |
137 | xArg, |
138 | XArg, |
139 | UIntArgBeg = oArg, |
140 | UIntArgEnd = XArg, |
141 | |
142 | fArg, |
143 | FArg, |
144 | eArg, |
145 | EArg, |
146 | gArg, |
147 | GArg, |
148 | aArg, |
149 | AArg, |
150 | DoubleArgBeg = fArg, |
151 | DoubleArgEnd = AArg, |
152 | |
153 | sArg, |
154 | pArg, |
155 | nArg, |
156 | PercentArg, |
157 | CArg, |
158 | SArg, |
159 | |
160 | |
161 | |
162 | |
163 | PArg, |
164 | |
165 | |
166 | |
167 | ZArg, |
168 | |
169 | |
170 | ObjCObjArg, |
171 | ObjCBeg = ObjCObjArg, |
172 | ObjCEnd = ObjCObjArg, |
173 | |
174 | |
175 | FreeBSDbArg, |
176 | FreeBSDDArg, |
177 | FreeBSDrArg, |
178 | FreeBSDyArg, |
179 | |
180 | |
181 | PrintErrno, |
182 | |
183 | PrintfConvBeg = ObjCObjArg, |
184 | PrintfConvEnd = PrintErrno, |
185 | |
186 | |
187 | ScanListArg, |
188 | ScanfConvBeg = ScanListArg, |
189 | ScanfConvEnd = ScanListArg |
190 | }; |
191 | |
192 | ConversionSpecifier(bool isPrintf = true) |
193 | : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr), |
194 | kind(InvalidSpecifier) {} |
195 | |
196 | ConversionSpecifier(bool isPrintf, const char *pos, Kind k) |
197 | : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {} |
198 | |
199 | const char *getStart() const { |
200 | return Position; |
201 | } |
202 | |
203 | StringRef getCharacters() const { |
204 | return StringRef(getStart(), getLength()); |
205 | } |
206 | |
207 | bool consumesDataArgument() const { |
208 | switch (kind) { |
209 | case PrintErrno: |
210 | assert(IsPrintf); |
211 | return false; |
212 | case PercentArg: |
213 | return false; |
214 | case InvalidSpecifier: |
215 | return false; |
216 | default: |
217 | return true; |
218 | } |
219 | } |
220 | |
221 | Kind getKind() const { return kind; } |
222 | void setKind(Kind k) { kind = k; } |
223 | unsigned getLength() const { |
224 | return EndScanList ? EndScanList - Position : 1; |
225 | } |
226 | void setEndScanList(const char *pos) { EndScanList = pos; } |
227 | |
228 | bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) || |
229 | kind == FreeBSDrArg || kind == FreeBSDyArg; } |
230 | bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } |
231 | bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; } |
232 | bool isDoubleArg() const { |
233 | return kind >= DoubleArgBeg && kind <= DoubleArgEnd; |
234 | } |
235 | |
236 | const char *toString() const; |
237 | |
238 | bool isPrintfKind() const { return IsPrintf; } |
239 | |
240 | Optional<ConversionSpecifier> getStandardSpecifier() const; |
241 | |
242 | protected: |
243 | bool IsPrintf; |
244 | const char *Position; |
245 | const char *EndScanList; |
246 | Kind kind; |
247 | }; |
248 | |
249 | class ArgType { |
250 | public: |
251 | enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, |
252 | AnyCharTy, CStrTy, WCStrTy, WIntTy }; |
253 | |
254 | enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic }; |
255 | |
256 | private: |
257 | const Kind K; |
258 | QualType T; |
259 | const char *Name = nullptr; |
260 | bool Ptr = false; |
261 | |
262 | |
263 | |
264 | enum class TypeKind { DontCare, SizeT, PtrdiffT }; |
265 | TypeKind TK = TypeKind::DontCare; |
266 | |
267 | public: |
268 | ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {} |
269 | ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {} |
270 | ArgType(CanQualType T) : K(SpecificTy), T(T) {} |
271 | |
272 | static ArgType Invalid() { return ArgType(InvalidTy); } |
273 | bool isValid() const { return K != InvalidTy; } |
274 | |
275 | bool isSizeT() const { return TK == TypeKind::SizeT; } |
276 | |
277 | bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; } |
278 | |
279 | |
280 | static ArgType PtrTo(const ArgType& A) { |
281 | (0) . __assert_fail ("A.K >= InvalidTy && \"ArgType cannot be pointer to invalid/unknown\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/FormatString.h", 281, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown"); |
282 | ArgType Res = A; |
283 | Res.Ptr = true; |
284 | return Res; |
285 | } |
286 | |
287 | |
288 | static ArgType makeSizeT(const ArgType &A) { |
289 | ArgType Res = A; |
290 | Res.TK = TypeKind::SizeT; |
291 | return Res; |
292 | } |
293 | |
294 | |
295 | |
296 | static ArgType makePtrdiffT(const ArgType &A) { |
297 | ArgType Res = A; |
298 | Res.TK = TypeKind::PtrdiffT; |
299 | return Res; |
300 | } |
301 | |
302 | MatchKind matchesType(ASTContext &C, QualType argTy) const; |
303 | |
304 | QualType getRepresentativeType(ASTContext &C) const; |
305 | |
306 | ArgType makeVectorType(ASTContext &C, unsigned NumElts) const; |
307 | |
308 | std::string getRepresentativeTypeName(ASTContext &C) const; |
309 | }; |
310 | |
311 | class OptionalAmount { |
312 | public: |
313 | enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; |
314 | |
315 | OptionalAmount(HowSpecified howSpecified, |
316 | unsigned amount, |
317 | const char *amountStart, |
318 | unsigned amountLength, |
319 | bool usesPositionalArg) |
320 | : start(amountStart), length(amountLength), hs(howSpecified), amt(amount), |
321 | UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {} |
322 | |
323 | OptionalAmount(bool valid = true) |
324 | : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0), |
325 | UsesPositionalArg(0), UsesDotPrefix(0) {} |
326 | |
327 | explicit OptionalAmount(unsigned Amount) |
328 | : start(nullptr), length(0), hs(Constant), amt(Amount), |
329 | UsesPositionalArg(false), UsesDotPrefix(false) {} |
330 | |
331 | bool isInvalid() const { |
332 | return hs == Invalid; |
333 | } |
334 | |
335 | HowSpecified getHowSpecified() const { return hs; } |
336 | void setHowSpecified(HowSpecified h) { hs = h; } |
337 | |
338 | bool hasDataArgument() const { return hs == Arg; } |
339 | |
340 | unsigned getArgIndex() const { |
341 | assert(hasDataArgument()); |
342 | return amt; |
343 | } |
344 | |
345 | unsigned getConstantAmount() const { |
346 | assert(hs == Constant); |
347 | return amt; |
348 | } |
349 | |
350 | const char *getStart() const { |
351 | |
352 | return start - UsesDotPrefix; |
353 | } |
354 | |
355 | unsigned getConstantLength() const { |
356 | assert(hs == Constant); |
357 | return length + UsesDotPrefix; |
358 | } |
359 | |
360 | ArgType getArgType(ASTContext &Ctx) const; |
361 | |
362 | void toString(raw_ostream &os) const; |
363 | |
364 | bool usesPositionalArg() const { return (bool) UsesPositionalArg; } |
365 | unsigned getPositionalArgIndex() const { |
366 | assert(hasDataArgument()); |
367 | return amt + 1; |
368 | } |
369 | |
370 | bool usesDotPrefix() const { return UsesDotPrefix; } |
371 | void setUsesDotPrefix() { UsesDotPrefix = true; } |
372 | |
373 | private: |
374 | const char *start; |
375 | unsigned length; |
376 | HowSpecified hs; |
377 | unsigned amt; |
378 | bool UsesPositionalArg : 1; |
379 | bool UsesDotPrefix; |
380 | }; |
381 | |
382 | |
383 | class FormatSpecifier { |
384 | protected: |
385 | LengthModifier LM; |
386 | OptionalAmount FieldWidth; |
387 | ConversionSpecifier CS; |
388 | OptionalAmount VectorNumElts; |
389 | |
390 | |
391 | |
392 | |
393 | bool UsesPositionalArg; |
394 | unsigned argIndex; |
395 | public: |
396 | FormatSpecifier(bool isPrintf) |
397 | : CS(isPrintf), VectorNumElts(false), |
398 | UsesPositionalArg(false), argIndex(0) {} |
399 | |
400 | void setLengthModifier(LengthModifier lm) { |
401 | LM = lm; |
402 | } |
403 | |
404 | void setUsesPositionalArg() { UsesPositionalArg = true; } |
405 | |
406 | void setArgIndex(unsigned i) { |
407 | argIndex = i; |
408 | } |
409 | |
410 | unsigned getArgIndex() const { |
411 | return argIndex; |
412 | } |
413 | |
414 | unsigned getPositionalArgIndex() const { |
415 | return argIndex + 1; |
416 | } |
417 | |
418 | const LengthModifier &getLengthModifier() const { |
419 | return LM; |
420 | } |
421 | |
422 | const OptionalAmount &getFieldWidth() const { |
423 | return FieldWidth; |
424 | } |
425 | |
426 | void setVectorNumElts(const OptionalAmount &Amt) { |
427 | VectorNumElts = Amt; |
428 | } |
429 | |
430 | const OptionalAmount &getVectorNumElts() const { |
431 | return VectorNumElts; |
432 | } |
433 | |
434 | void setFieldWidth(const OptionalAmount &Amt) { |
435 | FieldWidth = Amt; |
436 | } |
437 | |
438 | bool usesPositionalArg() const { return UsesPositionalArg; } |
439 | |
440 | bool hasValidLengthModifier(const TargetInfo &Target, |
441 | const LangOptions &LO) const; |
442 | |
443 | bool hasStandardLengthModifier() const; |
444 | |
445 | Optional<LengthModifier> getCorrectedLengthModifier() const; |
446 | |
447 | bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; |
448 | |
449 | bool hasStandardLengthConversionCombination() const; |
450 | |
451 | |
452 | |
453 | static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM); |
454 | }; |
455 | |
456 | } |
457 | |
458 | |
459 | |
460 | |
461 | namespace analyze_printf { |
462 | |
463 | class PrintfConversionSpecifier : |
464 | public analyze_format_string::ConversionSpecifier { |
465 | public: |
466 | PrintfConversionSpecifier() |
467 | : ConversionSpecifier(true, nullptr, InvalidSpecifier) {} |
468 | |
469 | PrintfConversionSpecifier(const char *pos, Kind k) |
470 | : ConversionSpecifier(true, pos, k) {} |
471 | |
472 | bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } |
473 | bool isDoubleArg() const { return kind >= DoubleArgBeg && |
474 | kind <= DoubleArgEnd; } |
475 | |
476 | static bool classof(const analyze_format_string::ConversionSpecifier *CS) { |
477 | return CS->isPrintfKind(); |
478 | } |
479 | }; |
480 | |
481 | using analyze_format_string::ArgType; |
482 | using analyze_format_string::LengthModifier; |
483 | using analyze_format_string::OptionalAmount; |
484 | using analyze_format_string::OptionalFlag; |
485 | |
486 | class PrintfSpecifier : public analyze_format_string::FormatSpecifier { |
487 | OptionalFlag HasThousandsGrouping; |
488 | OptionalFlag IsLeftJustified; |
489 | OptionalFlag HasPlusPrefix; |
490 | OptionalFlag HasSpacePrefix; |
491 | OptionalFlag HasAlternativeForm; |
492 | OptionalFlag HasLeadingZeroes; |
493 | OptionalFlag HasObjCTechnicalTerm; |
494 | OptionalFlag IsPrivate; |
495 | OptionalFlag IsPublic; |
496 | OptionalFlag IsSensitive; |
497 | OptionalAmount Precision; |
498 | StringRef MaskType; |
499 | |
500 | ArgType getScalarArgType(ASTContext &Ctx, bool IsObjCLiteral) const; |
501 | |
502 | public: |
503 | PrintfSpecifier() |
504 | : FormatSpecifier( true), HasThousandsGrouping("'"), |
505 | IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "), |
506 | HasAlternativeForm("#"), HasLeadingZeroes("0"), |
507 | HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public"), |
508 | IsSensitive("sensitive") {} |
509 | |
510 | static PrintfSpecifier Parse(const char *beg, const char *end); |
511 | |
512 | |
513 | void setConversionSpecifier(const PrintfConversionSpecifier &cs) { |
514 | CS = cs; |
515 | } |
516 | void setHasThousandsGrouping(const char *position) { |
517 | HasThousandsGrouping.setPosition(position); |
518 | } |
519 | void setIsLeftJustified(const char *position) { |
520 | IsLeftJustified.setPosition(position); |
521 | } |
522 | void setHasPlusPrefix(const char *position) { |
523 | HasPlusPrefix.setPosition(position); |
524 | } |
525 | void setHasSpacePrefix(const char *position) { |
526 | HasSpacePrefix.setPosition(position); |
527 | } |
528 | void setHasAlternativeForm(const char *position) { |
529 | HasAlternativeForm.setPosition(position); |
530 | } |
531 | void setHasLeadingZeros(const char *position) { |
532 | HasLeadingZeroes.setPosition(position); |
533 | } |
534 | void setHasObjCTechnicalTerm(const char *position) { |
535 | HasObjCTechnicalTerm.setPosition(position); |
536 | } |
537 | void setIsPrivate(const char *position) { IsPrivate.setPosition(position); } |
538 | void setIsPublic(const char *position) { IsPublic.setPosition(position); } |
539 | void setIsSensitive(const char *position) { |
540 | IsSensitive.setPosition(position); |
541 | } |
542 | void setUsesPositionalArg() { UsesPositionalArg = true; } |
543 | |
544 | |
545 | |
546 | const PrintfConversionSpecifier &getConversionSpecifier() const { |
547 | return cast<PrintfConversionSpecifier>(CS); |
548 | } |
549 | |
550 | void setPrecision(const OptionalAmount &Amt) { |
551 | Precision = Amt; |
552 | Precision.setUsesDotPrefix(); |
553 | } |
554 | |
555 | const OptionalAmount &getPrecision() const { |
556 | return Precision; |
557 | } |
558 | |
559 | bool consumesDataArgument() const { |
560 | return getConversionSpecifier().consumesDataArgument(); |
561 | } |
562 | |
563 | |
564 | |
565 | |
566 | |
567 | |
568 | ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const; |
569 | |
570 | const OptionalFlag &hasThousandsGrouping() const { |
571 | return HasThousandsGrouping; |
572 | } |
573 | const OptionalFlag &isLeftJustified() const { return IsLeftJustified; } |
574 | const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; } |
575 | const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; } |
576 | const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; } |
577 | const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; } |
578 | const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; } |
579 | const OptionalFlag &isPrivate() const { return IsPrivate; } |
580 | const OptionalFlag &isPublic() const { return IsPublic; } |
581 | const OptionalFlag &isSensitive() const { return IsSensitive; } |
582 | bool usesPositionalArg() const { return UsesPositionalArg; } |
583 | |
584 | StringRef getMaskType() const { return MaskType; } |
585 | void setMaskType(StringRef S) { MaskType = S; } |
586 | |
587 | |
588 | |
589 | |
590 | bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx, |
591 | bool IsObjCLiteral); |
592 | |
593 | void toString(raw_ostream &os) const; |
594 | |
595 | |
596 | bool hasValidPlusPrefix() const; |
597 | bool hasValidAlternativeForm() const; |
598 | bool hasValidLeadingZeros() const; |
599 | bool hasValidSpacePrefix() const; |
600 | bool hasValidLeftJustified() const; |
601 | bool hasValidThousandsGroupingPrefix() const; |
602 | |
603 | bool hasValidPrecision() const; |
604 | bool hasValidFieldWidth() const; |
605 | }; |
606 | } |
607 | |
608 | |
609 | |
610 | |
611 | namespace analyze_scanf { |
612 | |
613 | class ScanfConversionSpecifier : |
614 | public analyze_format_string::ConversionSpecifier { |
615 | public: |
616 | ScanfConversionSpecifier() |
617 | : ConversionSpecifier(false, nullptr, InvalidSpecifier) {} |
618 | |
619 | ScanfConversionSpecifier(const char *pos, Kind k) |
620 | : ConversionSpecifier(false, pos, k) {} |
621 | |
622 | static bool classof(const analyze_format_string::ConversionSpecifier *CS) { |
623 | return !CS->isPrintfKind(); |
624 | } |
625 | }; |
626 | |
627 | using analyze_format_string::ArgType; |
628 | using analyze_format_string::LengthModifier; |
629 | using analyze_format_string::OptionalAmount; |
630 | using analyze_format_string::OptionalFlag; |
631 | |
632 | class ScanfSpecifier : public analyze_format_string::FormatSpecifier { |
633 | OptionalFlag SuppressAssignment; |
634 | public: |
635 | ScanfSpecifier() : |
636 | FormatSpecifier( false), |
637 | SuppressAssignment("*") {} |
638 | |
639 | void setSuppressAssignment(const char *position) { |
640 | SuppressAssignment.setPosition(position); |
641 | } |
642 | |
643 | const OptionalFlag &getSuppressAssignment() const { |
644 | return SuppressAssignment; |
645 | } |
646 | |
647 | void setConversionSpecifier(const ScanfConversionSpecifier &cs) { |
648 | CS = cs; |
649 | } |
650 | |
651 | const ScanfConversionSpecifier &getConversionSpecifier() const { |
652 | return cast<ScanfConversionSpecifier>(CS); |
653 | } |
654 | |
655 | bool consumesDataArgument() const { |
656 | return CS.consumesDataArgument() && !SuppressAssignment; |
657 | } |
658 | |
659 | ArgType getArgType(ASTContext &Ctx) const; |
660 | |
661 | bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt, |
662 | ASTContext &Ctx); |
663 | |
664 | void toString(raw_ostream &os) const; |
665 | |
666 | static ScanfSpecifier Parse(const char *beg, const char *end); |
667 | }; |
668 | |
669 | } |
670 | |
671 | |
672 | |
673 | |
674 | namespace analyze_format_string { |
675 | |
676 | enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; |
677 | |
678 | class FormatStringHandler { |
679 | public: |
680 | FormatStringHandler() {} |
681 | virtual ~FormatStringHandler(); |
682 | |
683 | virtual void HandleNullChar(const char *nullCharacter) {} |
684 | |
685 | virtual void HandlePosition(const char *startPos, unsigned posLen) {} |
686 | |
687 | virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, |
688 | PositionContext p) {} |
689 | |
690 | virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {} |
691 | |
692 | virtual void HandleIncompleteSpecifier(const char *startSpecifier, |
693 | unsigned specifierLen) {} |
694 | |
695 | virtual void HandleEmptyObjCModifierFlag(const char *startFlags, |
696 | unsigned flagsLen) {} |
697 | |
698 | virtual void HandleInvalidObjCModifierFlag(const char *startFlag, |
699 | unsigned flagLen) {} |
700 | |
701 | virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart, |
702 | const char *flagsEnd, |
703 | const char *conversionPosition) {} |
704 | |
705 | |
706 | virtual bool HandleInvalidPrintfConversionSpecifier( |
707 | const analyze_printf::PrintfSpecifier &FS, |
708 | const char *startSpecifier, |
709 | unsigned specifierLen) { |
710 | return true; |
711 | } |
712 | |
713 | virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, |
714 | const char *startSpecifier, |
715 | unsigned specifierLen) { |
716 | return true; |
717 | } |
718 | |
719 | |
720 | virtual void handleInvalidMaskType(StringRef MaskType) {} |
721 | |
722 | |
723 | |
724 | virtual bool HandleInvalidScanfConversionSpecifier( |
725 | const analyze_scanf::ScanfSpecifier &FS, |
726 | const char *startSpecifier, |
727 | unsigned specifierLen) { |
728 | return true; |
729 | } |
730 | |
731 | virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, |
732 | const char *startSpecifier, |
733 | unsigned specifierLen) { |
734 | return true; |
735 | } |
736 | |
737 | virtual void HandleIncompleteScanList(const char *start, const char *end) {} |
738 | }; |
739 | |
740 | bool ParsePrintfString(FormatStringHandler &H, |
741 | const char *beg, const char *end, const LangOptions &LO, |
742 | const TargetInfo &Target, bool isFreeBSDKPrintf); |
743 | |
744 | bool ParseFormatStringHasSArg(const char *beg, const char *end, |
745 | const LangOptions &LO, const TargetInfo &Target); |
746 | |
747 | bool ParseScanfString(FormatStringHandler &H, |
748 | const char *beg, const char *end, const LangOptions &LO, |
749 | const TargetInfo &Target); |
750 | |
751 | } |
752 | } |
753 | #endif |
754 | |