diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-02-11 09:27:41 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-02-11 09:27:41 +0000 |
commit | 5c41ee8c49995fb4fd76d686b239c15cbab261ea (patch) | |
tree | b8fc243b142bb4fdd68ee1783c2aa8cd4feb9cdc /lib/Sema/SemaChecking.cpp | |
parent | 824d7ea07a4e9208925daa6ae9289fb2b39bce9f (diff) |
Patch by Cristian Draghici:
Enhance the printf format string checking when using the format
specifier flags ' ', '0', '+' with the 'p' or 's' conversions (since
they are nonsensical and undefined). This is similar to GCC's
checking.
Also warning when a precision is used with the 'p' conversin
specifier, since it has no meaning.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95869 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 8451023761..3a77552f48 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1080,6 +1080,9 @@ private: bool HandleAmount(const analyze_printf::OptionalAmount &Amt, unsigned MissingArgDiag, unsigned BadTypeDiag, const char *startSpecifier, unsigned specifierLen); + void HandleFlags(const analyze_printf::FormatSpecifier &FS, + llvm::StringRef flag, llvm::StringRef cspec, + const char *startSpecifier, unsigned specifierLen); bool MatchType(QualType A, QualType B, bool ignoreSign); @@ -1175,6 +1178,16 @@ bool CheckPrintfHandler::MatchType(QualType A, QualType B, bool ignoreSign) { return false; } +void CheckPrintfHandler::HandleFlags(const analyze_printf::FormatSpecifier &FS, + llvm::StringRef flag, + llvm::StringRef cspec, + const char *startSpecifier, + unsigned specifierLen) { + const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier(); + S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_nonsensical_flag) + << flag << cspec << getFormatSpecifierRange(startSpecifier, specifierLen); +} + bool CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt, unsigned MissingArgDiag, @@ -1214,7 +1227,8 @@ CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt, } bool -CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS, +CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier + &FS, const char *startSpecifier, unsigned specifierLen) { @@ -1262,7 +1276,25 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier // Continue checking the other format specifiers. return true; } - + + if (CS.getKind() == ConversionSpecifier::VoidPtrArg) { + if (FS.getPrecision().getHowSpecified() != OptionalAmount::NotSpecified) + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_nonsensical_precision) + << CS.getCharacters() + << getFormatSpecifierRange(startSpecifier, specifierLen); + } + if (CS.getKind() == ConversionSpecifier::VoidPtrArg || + CS.getKind() == ConversionSpecifier::CStrArg) { + // FIXME: Instead of using "0", "+", etc., eventually get them from + // the FormatSpecifier. + if (FS.hasLeadingZeros()) + HandleFlags(FS, "0", CS.getCharacters(), startSpecifier, specifierLen); + if (FS.hasPlusPrefix()) + HandleFlags(FS, "+", CS.getCharacters(), startSpecifier, specifierLen); + if (FS.hasSpacePrefix()) + HandleFlags(FS, " ", CS.getCharacters(), startSpecifier, specifierLen); + } // The remaining checks depend on the data arguments. if (HasVAListArg) |