aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Analysis/Analyses/PrintfFormatString.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Analysis/Analyses/PrintfFormatString.h')
-rw-r--r--include/clang/Analysis/Analyses/PrintfFormatString.h182
1 files changed, 182 insertions, 0 deletions
diff --git a/include/clang/Analysis/Analyses/PrintfFormatString.h b/include/clang/Analysis/Analyses/PrintfFormatString.h
new file mode 100644
index 0000000000..978486d271
--- /dev/null
+++ b/include/clang/Analysis/Analyses/PrintfFormatString.h
@@ -0,0 +1,182 @@
+//==- PrintfFormatStrings.h - Analysis of printf format strings --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Handling of format string in printf and friends. The structure of format
+// strings for fprintf() are described in C99 7.19.6.1.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FPRINTF_FORMAT_H
+#define LLVM_CLANG_FPRINTF_FORMAT_H
+
+#include <cassert>
+
+namespace clang {
+namespace printf {
+
+class ConversionSpecifier {
+public:
+ enum Kind {
+ InvalidSpecifier = 0,
+ dArg, // 'd'
+ iArg, // 'i',
+ oArg, // 'o',
+ uArg, // 'u',
+ xArg, // 'x',
+ XArg, // 'X',
+ fArg, // 'f',
+ FArg, // 'F',
+ eArg, // 'e',
+ EArg, // 'E',
+ gArg, // 'g',
+ GArg, // 'G',
+ aArg, // 'a',
+ AArg, // 'A',
+ IntAsCharArg, // 'c'
+ CStrArg, // 's'
+ VoidPtrArg, // 'p'
+ OutIntPtrArg, // 'n'
+ PercentArg, // '%'
+ IntArgBeg = dArg,
+ IntArgEnd = iArg,
+ UIntArgBeg = oArg,
+ UIntArgEnd = XArg,
+ DoubleArgBeg = fArg,
+ DoubleArgEnd = AArg
+ };
+
+ ConversionSpecifier(Kind k) : kind(k) {}
+
+ bool isIntArg() const { return kind >= dArg && kind <= iArg; }
+ bool isUIntArg() const { return kind >= oArg && kind <= XArg; }
+ bool isDoubleArg() const { return kind >= fArg && kind <= AArg; }
+ Kind getKind() const { return kind; }
+
+private:
+ const Kind kind;
+};
+
+enum LengthModifier {
+ None,
+ AsChar, // 'hh'
+ AsShort, // 'h'
+ AsLong, // 'l'
+ AsLongLong, // 'll'
+ AsIntMax, // 'j'
+ AsSizeT, // 'z'
+ AsPtrDiff, // 't'
+ AsLongDouble // 'L'
+};
+
+enum Flags {
+ LeftJustified = 0x1,
+ PlusPrefix = 0x2,
+ SpacePrefix = 0x4,
+ AlternativeForm = 0x8,
+ LeadingZeroes = 0x16
+};
+
+class OptionalAmount {
+public:
+ enum HowSpecified { NotSpecified, Constant, Arg };
+
+ OptionalAmount(HowSpecified h = NotSpecified) : hs(h), amt(0) {}
+ OptionalAmount(unsigned i) : hs(Constant), amt(i) {}
+
+ HowSpecified getHowSpecified() const { return hs; }
+
+ unsigned getConstantAmount() const {
+ assert(hs == Constant);
+ return amt;
+ }
+
+ unsigned getArgumentsConsumed() {
+ return hs == Arg ? 1 : 0;
+ }
+
+private:
+ HowSpecified hs;
+ unsigned amt;
+};
+
+class FormatSpecifier {
+ unsigned conversionSpecifier : 6;
+ unsigned lengthModifier : 5;
+ unsigned flags : 5;
+ OptionalAmount FieldWidth;
+ OptionalAmount Precision;
+public:
+ FormatSpecifier() : conversionSpecifier(0), lengthModifier(0), flags(0) {}
+
+ static FormatSpecifier Parse(const char *beg, const char *end);
+
+ // Methods for incrementally constructing the FormatSpecifier.
+ void setConversionSpecifier(ConversionSpecifier cs) {
+ conversionSpecifier = (unsigned) cs.getKind();
+ }
+ void setLengthModifier(LengthModifier lm) {
+ lengthModifier = (unsigned) lm;
+ }
+ void setIsLeftJustified() { flags |= LeftJustified; }
+ void setHasPlusPrefix() { flags |= PlusPrefix; }
+ void setHasSpacePrefix() { flags |= SpacePrefix; }
+ void setHasAlternativeForm() { flags |= AlternativeForm; }
+ void setHasLeadingZeros() { flags |= LeadingZeroes; }
+
+ // Methods for querying the format specifier.
+
+ ConversionSpecifier getConversionSpecifier() const {
+ return (ConversionSpecifier::Kind) conversionSpecifier;
+ }
+
+ LengthModifier getLengthModifier() const {
+ return (LengthModifier) lengthModifier;
+ }
+
+ void setFieldWidth(const OptionalAmount &Amt) {
+ FieldWidth = Amt;
+ }
+
+ void setPrecision(const OptionalAmount &Amt) {
+ Precision = Amt;
+ }
+
+ bool isLeftJustified() const { return flags & LeftJustified; }
+ bool hasPlusPrefix() const { return flags & PlusPrefix; }
+ bool hasAlternativeForm() const { return flags & AlternativeForm; }
+ bool hasLeadingZeros() const { return flags & LeadingZeroes; }
+};
+
+
+class FormatStringHandler {
+public:
+ FormatStringHandler() {}
+ virtual ~FormatStringHandler();
+
+ virtual void HandleIncompleteFormatSpecifier(const char *startSpecifier,
+ const char *endSpecifier) {}
+
+ virtual void HandleNullChar(const char *nullCharacter) {}
+
+ virtual void HandleIncompletePrecision(const char *periodChar) {}
+
+ virtual void HandleInvalidConversionSpecifier(const char *conversionChar) {}
+
+ virtual void HandleFormatSpecifier(const FormatSpecifier &FS,
+ const char *startSpecifier,
+ const char *endSpecifier) {}
+};
+
+bool ParseFormatString(FormatStringHandler &H,
+ const char *beg, const char *end);
+
+
+} // end printf namespace
+} // end clang namespace
+#endif