diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-02-26 19:18:41 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-02-26 19:18:41 +0000 |
commit | 7f70dc85d5055c19c8003f43a59135de211ad1b9 (patch) | |
tree | d00ab441a40de77aee9b344a971692df998af4b5 /lib/Analysis/PrintfFormatString.cpp | |
parent | e7c5c93e37ad2db5d1bc0b11a3d67c346c02de8a (diff) |
For printf format string checking, move the tracking of the data argument index out of
Sema and into analyze_printf::ParseFormatString(). Also use a bitvector to determine
what arguments have been covered (instead of just checking to see if the last argument consumed is the max argument). This is prep. for support positional arguments (an IEEE extension).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97248 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/PrintfFormatString.cpp')
-rw-r--r-- | lib/Analysis/PrintfFormatString.cpp | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index 3aee57cb81..9c0f813964 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -62,7 +62,8 @@ public: // Methods for parsing format strings. //===----------------------------------------------------------------------===// -static OptionalAmount ParseAmount(const char *&Beg, const char *E) { +static OptionalAmount ParseAmount(const char *&Beg, const char *E, + unsigned &argIndex) { const char *I = Beg; UpdateOnReturn <const char*> UpdateBeg(Beg, I); @@ -78,11 +79,11 @@ static OptionalAmount ParseAmount(const char *&Beg, const char *E) { } if (foundDigits) - return OptionalAmount(accumulator, Beg); + return OptionalAmount(OptionalAmount::Constant, accumulator, Beg); if (c == '*') { ++I; - return OptionalAmount(OptionalAmount::Arg, Beg); + return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg); } break; @@ -93,7 +94,8 @@ static OptionalAmount ParseAmount(const char *&Beg, const char *E) { static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H, const char *&Beg, - const char *E) { + const char *E, + unsigned &argIndex) { using namespace clang::analyze_printf; @@ -149,7 +151,7 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H, } // Look for the field width (if any). - FS.setFieldWidth(ParseAmount(I, E)); + FS.setFieldWidth(ParseAmount(I, E, argIndex)); if (I == E) { // No more characters left? @@ -165,7 +167,7 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H, return true; } - FS.setPrecision(ParseAmount(I, E)); + FS.setPrecision(ParseAmount(I, E, argIndex)); if (I == E) { // No more characters left? @@ -241,20 +243,26 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H, // Glibc specific. case 'm': k = ConversionSpecifier::PrintErrno; break; } - FS.setConversionSpecifier(ConversionSpecifier(conversionPosition, k)); + ConversionSpecifier CS(conversionPosition, k); + FS.setConversionSpecifier(CS); + if (CS.consumesDataArgument()) + FS.setArgIndex(argIndex++); if (k == ConversionSpecifier::InvalidSpecifier) { - H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg); - return false; // Keep processing format specifiers. + // Assume the conversion takes one argument. + return !H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg); } return FormatSpecifierResult(Start, FS); } bool clang::analyze_printf::ParseFormatString(FormatStringHandler &H, const char *I, const char *E) { + + unsigned argIndex = 0; + // Keep looking for a format specifier until we have exhausted the string. while (I != E) { - const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E); + const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E, argIndex); // Did a fail-stop error of any kind occur when parsing the specifier? // If so, don't do any more processing. if (FSR.shouldStop()) @@ -430,7 +438,7 @@ ArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const { return Ctx.LongDoubleTy; return Ctx.DoubleTy; } - + switch (CS.getKind()) { case ConversionSpecifier::CStrArg: return ArgTypeResult(LM == AsWideChar ? ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy); @@ -438,11 +446,11 @@ ArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const { // FIXME: This appears to be Mac OS X specific. return ArgTypeResult::WCStrTy; case ConversionSpecifier::CArg: - return Ctx.WCharTy; + return Ctx.WCharTy; default: break; } - + // FIXME: Handle other cases. return ArgTypeResult(); } |