diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Analysis/FormatString.cpp | 23 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 27 |
2 files changed, 45 insertions, 5 deletions
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp index f70086b883..73063b5132 100644 --- a/lib/Analysis/FormatString.cpp +++ b/lib/Analysis/FormatString.cpp @@ -527,6 +527,29 @@ const char *ConversionSpecifier::toString() const { return NULL; } +llvm::Optional<ConversionSpecifier> +ConversionSpecifier::getStandardSpecifier() const { + ConversionSpecifier::Kind NewKind; + + switch (getKind()) { + default: + return llvm::Optional<ConversionSpecifier>(); + case DArg: + NewKind = dArg; + break; + case UArg: + NewKind = uArg; + break; + case OArg: + NewKind = oArg; + break; + } + + ConversionSpecifier FixedCS(*this); + FixedCS.setKind(NewKind); + return FixedCS; +} + //===----------------------------------------------------------------------===// // Methods on OptionalAmount. //===----------------------------------------------------------------------===// diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 2ae1d6ee91..b46081dc99 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2095,11 +2095,28 @@ void CheckFormatHandler::HandleNonStandardLengthModifier( void CheckFormatHandler::HandleNonStandardConversionSpecifier( const analyze_format_string::ConversionSpecifier &CS, const char *startSpecifier, unsigned specifierLen) { - EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << CS.toString() - << 1, - getLocationOfByte(CS.getStart()), - /*IsStringLocation*/true, - getSpecifierRange(startSpecifier, specifierLen)); + using namespace analyze_format_string; + + // See if we know how to fix this conversion specifier. + llvm::Optional<ConversionSpecifier> FixedCS = CS.getStandardSpecifier(); + if (FixedCS) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) + << CS.toString() << /*conversion specifier*/1, + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + + CharSourceRange CSRange = getSpecifierRange(CS.getStart(), CS.getLength()); + S.Diag(getLocationOfByte(CS.getStart()), diag::note_format_fix_specifier) + << FixedCS->toString() + << FixItHint::CreateReplacement(CSRange, FixedCS->toString()); + } else { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) + << CS.toString() << /*conversion specifier*/1, + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + } } void CheckFormatHandler::HandlePosition(const char *startPos, |