aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-02-11 09:27:41 +0000
committerTed Kremenek <kremenek@apple.com>2010-02-11 09:27:41 +0000
commit5c41ee8c49995fb4fd76d686b239c15cbab261ea (patch)
treeb8fc243b142bb4fdd68ee1783c2aa8cd4feb9cdc /lib/Sema/SemaChecking.cpp
parent824d7ea07a4e9208925daa6ae9289fb2b39bce9f (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.cpp36
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)