aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-02-01 19:28:15 +0000
committerTed Kremenek <kremenek@apple.com>2010-02-01 19:28:15 +0000
commit180f2840d1d8bcb2139bfb53e2d88eda280e939e (patch)
tree6323b5ef907a1f2f47d62005a4c1f4d45287e3f8 /lib/Sema/SemaChecking.cpp
parentabb485f0b58dd3d2da20f9b34f99695899a68cf2 (diff)
Format string checking: selectively ignore implicit casts to 'int'
when checking if the format specifier matches the type of the data argument and the length modifier indicates the data type is 'char' or 'short'. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94992 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r--lib/Sema/SemaChecking.cpp23
1 files changed, 17 insertions, 6 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 4e2e9c7376..5db7038405 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -1280,14 +1280,25 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
// format specifier.
const Expr *Ex = getDataArg(NumConversions);
const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context);
-
+
if (const QualType *T = ATR.getSpecificType()) {
if (!MatchType(*T, Ex->getType(), true)) {
- S.Diag(getLocationOfByte(CS.getStart()),
- diag::warn_printf_conversion_argument_type_mismatch)
- << *T << Ex->getType()
- << getFormatSpecifierRange(startSpecifier, specifierLen)
- << Ex->getSourceRange();
+ // Check if we didn't match because of an implicit cast from a 'char'
+ // or 'short' to an 'int'. This is done because printf is a varargs
+ // function.
+ bool hasError = true;
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex))
+ if (ICE->getType() == S.Context.IntTy) {
+ Ex = ICE->getSubExpr();
+ hasError = !MatchType(*T, Ex->getType(), true);
+ }
+
+ if (hasError)
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << *T << Ex->getType()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange();
}
return true;
}