aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/PrintfFormatString.cpp
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2012-02-15 09:59:46 +0000
committerHans Wennborg <hans@hanshq.net>2012-02-15 09:59:46 +0000
commitbe6126a2a784e1446460b8d15c2b26f880c871fc (patch)
treedcd82b29009df602ff45a73ab58053e9e883d25a /lib/Analysis/PrintfFormatString.cpp
parent37ce0104b182c9410cf2a76fe5a63a81dac876ac (diff)
Make -Wformat fix-its preserve original conversion specifiers.
This commit makes PrintfSpecifier::fixType() and ScanfSpecifier::fixType() only fix a conversion specification enough that Clang wouldn't warn about it, as opposed to always changing it to use the "canonical" conversion specifier. (PR11975) This preserves the user's choice of conversion specifier in cases like: printf("%a", (long double)1); where we previously suggested "%Lf", we now suggest "%La" printf("%x", (long)1); where we previously suggested "%ld", we now suggest "%lx". git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150578 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/PrintfFormatString.cpp')
-rw-r--r--lib/Analysis/PrintfFormatString.cpp12
1 files changed, 8 insertions, 4 deletions
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index 6da37fc44a..ff0174e3c3 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -336,7 +336,8 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx,
return ArgTypeResult();
}
-bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt) {
+bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
+ ASTContext &Ctx, bool IsObjCLiteral) {
// Handle strings first (char *, wchar_t *)
if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
CS.setKind(ConversionSpecifier::sArg);
@@ -432,6 +433,11 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt) {
}
}
+ // If fixing the length modifier was enough, we are done.
+ const analyze_printf::ArgTypeResult &ATR = getArgType(Ctx, IsObjCLiteral);
+ if (hasValidLengthModifier() && ATR.isValid() && ATR.matchesType(Ctx, QT))
+ return true;
+
// 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()) {
@@ -451,9 +457,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt) {
HasAlternativeForm = 0;
}
else if (QT->isUnsignedIntegerType()) {
- // Preserve the original formatting, e.g. 'X', 'o'.
- if (!cast<PrintfConversionSpecifier>(CS).isUIntArg())
- CS.setKind(ConversionSpecifier::uArg);
+ CS.setKind(ConversionSpecifier::uArg);
HasAlternativeForm = 0;
HasPlusPrefix = 0;
} else {