summaryrefslogtreecommitdiffstats
path: root/lib/Analysis/PrintfFormatString.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/PrintfFormatString.cpp')
-rw-r--r--lib/Analysis/PrintfFormatString.cpp34
1 files changed, 27 insertions, 7 deletions
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index 2fa5a88..8f151b9 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/FormatString.h"
-#include "clang/Basic/TargetInfo.h"
#include "FormatStringParsing.h"
+#include "clang/Basic/TargetInfo.h"
using clang::analyze_format_string::ArgType;
using clang::analyze_format_string::FormatStringHandler;
@@ -359,17 +359,19 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
case ConversionSpecifier::sArg:
if (LM.getKind() == LengthModifier::AsWideChar) {
if (IsObjCLiteral)
- return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
+ return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
+ "const unichar *");
return ArgType(ArgType::WCStrTy, "wchar_t *");
}
return ArgType::CStrTy;
case ConversionSpecifier::SArg:
if (IsObjCLiteral)
- return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
+ return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
+ "const unichar *");
return ArgType(ArgType::WCStrTy, "wchar_t *");
case ConversionSpecifier::CArg:
if (IsObjCLiteral)
- return Ctx.UnsignedShortTy;
+ return ArgType(Ctx.UnsignedShortTy, "unichar");
return ArgType(Ctx.WCharTy, "wchar_t");
case ConversionSpecifier::pArg:
return ArgType::CPointerTy;
@@ -494,11 +496,29 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
}
// Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
- if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x))
+ if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
namedTypeToLengthModifier(QT, LM);
- // If fixing the length modifier was enough, we are done.
+ // If fixing the length modifier was enough, we might be done.
if (hasValidLengthModifier(Ctx.getTargetInfo())) {
+ // If we're going to offer a fix anyway, make sure the sign matches.
+ switch (CS.getKind()) {
+ case ConversionSpecifier::uArg:
+ case ConversionSpecifier::UArg:
+ if (QT->isSignedIntegerType())
+ CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
+ break;
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::DArg:
+ case ConversionSpecifier::iArg:
+ if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
+ CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
+ break;
+ default:
+ // Other specifiers do not have signed/unsigned variants.
+ break;
+ }
+
const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
if (ATR.isValid() && ATR.matchesType(Ctx, QT))
return true;
@@ -506,7 +526,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
// Set conversion specifier and disable any flags which do not apply to it.
// Let typedefs to char fall through to int, as %c is silly for uint8_t.
- if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) {
+ if (!isa<TypedefType>(QT) && QT->isCharType()) {
CS.setKind(ConversionSpecifier::cArg);
LM.setKind(LengthModifier::None);
Precision.setHowSpecified(OptionalAmount::NotSpecified);
OpenPOWER on IntegriCloud