diff options
author | Hans Wennborg <hans@hanshq.net> | 2012-02-15 09:59:46 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2012-02-15 09:59:46 +0000 |
commit | d99d688358d9383b4cedb824d6ddfe36e2aa4a6d (patch) | |
tree | 6082e708fb78bc39e9fcdec2d78ceefecc0b88e7 /clang/lib/Analysis/ScanfFormatString.cpp | |
parent | f12cea425709e39992e4c3464fbca8654d11ce5a (diff) | |
download | bcm5719-llvm-d99d688358d9383b4cedb824d6ddfe36e2aa4a6d.tar.gz bcm5719-llvm-d99d688358d9383b4cedb824d6ddfe36e2aa4a6d.zip |
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".
llvm-svn: 150578
Diffstat (limited to 'clang/lib/Analysis/ScanfFormatString.cpp')
-rw-r--r-- | clang/lib/Analysis/ScanfFormatString.cpp | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/clang/lib/Analysis/ScanfFormatString.cpp b/clang/lib/Analysis/ScanfFormatString.cpp index c1cdef86327..5990a56c35c 100644 --- a/clang/lib/Analysis/ScanfFormatString.cpp +++ b/clang/lib/Analysis/ScanfFormatString.cpp @@ -307,8 +307,8 @@ ScanfArgTypeResult ScanfSpecifier::getArgType(ASTContext &Ctx) const { return ScanfArgTypeResult(); } -bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt) -{ +bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, + ASTContext &Ctx) { if (!QT->isPointerType()) return false; @@ -390,17 +390,19 @@ bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt) } } + // If fixing the length modifier was enough, we are done. + const analyze_scanf::ScanfArgTypeResult &ATR = getArgType(Ctx); + if (hasValidLengthModifier() && ATR.isValid() && ATR.matchesType(Ctx, QT)) + return true; + // Figure out the conversion specifier. if (PT->isRealFloatingType()) CS.setKind(ConversionSpecifier::fArg); else if (PT->isSignedIntegerType()) CS.setKind(ConversionSpecifier::dArg); - else if (PT->isUnsignedIntegerType()) { - // Preserve the original formatting, e.g. 'X', 'o'. - if (!CS.isUIntArg()) { - CS.setKind(ConversionSpecifier::uArg); - } - } else + else if (PT->isUnsignedIntegerType()) + CS.setKind(ConversionSpecifier::uArg); + else llvm_unreachable("Unexpected type"); return true; |