aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Analysis/Analyses/PrintfFormatString.h
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-01-27 23:43:25 +0000
committerTed Kremenek <kremenek@apple.com>2010-01-27 23:43:25 +0000
commit8f0a1c73fd2b83afd4b1fce6f964535b51d13659 (patch)
treee3d49128125c91960ce67fbd81bf63763f309284 /include/clang/Analysis/Analyses/PrintfFormatString.h
parent802080652857744ba2bb53254a1a623fe7486e8c (diff)
Add skeleton for a more structured way to analyzing pring format
strings than what we currently have in Sema. This is both an experiment and a WIP. The idea is simple: parse the format string incrementally, constructing a well-structure representation of each format specifier. Each format specifier is then handed back one-by-one to a client via a callback. Malformed format strings are also handled with callbacks. The idea is to separate the parsing of the format string from the emission of diagnostics. Currently what we have in Sema for handling format strings is a mongrel of both that is hard to follow and difficult to modify (I can apply this label since I'm the original author of that code). This is in libAnalysis as it is reasonable generic and can potentially be used both by libSema and libChecker. Comments welcome. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94702 91177308-0d34-0410-b5e6-96231b3b80d8
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