[cfe-commits] r163772 - in /cfe/trunk: include/clang/Analysis/Analyses/FormatString.h lib/Analysis/FormatString.cpp lib/Sema/SemaChecking.cpp test/FixIt/format-darwin.m test/Sema/format-strings-darwin.c
Jordan Rose
jordan_rose at apple.com
Wed Sep 12 19:11:15 PDT 2012
Author: jrose
Date: Wed Sep 12 21:11:15 2012
New Revision: 163772
URL: http://llvm.org/viewvc/llvm-project?rev=163772&view=rev
Log:
Format strings: offer a fixit for Darwin's %D/%U/%O to ISO %d/%u/%o.
<rdar://problem/12061922>
Modified:
cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
cfe/trunk/lib/Analysis/FormatString.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/test/FixIt/format-darwin.m
cfe/trunk/test/Sema/format-strings-darwin.c
Modified: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=163772&r1=163771&r2=163772&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Wed Sep 12 21:11:15 2012
@@ -162,7 +162,7 @@
ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg
};
- ConversionSpecifier(bool isPrintf)
+ ConversionSpecifier(bool isPrintf = true)
: IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {}
ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
@@ -200,6 +200,8 @@
const char *toString() const;
bool isPrintfKind() const { return IsPrintf; }
+
+ llvm::Optional<ConversionSpecifier> getStandardSpecifier() const;
protected:
bool IsPrintf;
Modified: cfe/trunk/lib/Analysis/FormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=163772&r1=163771&r2=163772&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/FormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/FormatString.cpp Wed Sep 12 21:11:15 2012
@@ -527,6 +527,29 @@
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.
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=163772&r1=163771&r2=163772&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Sep 12 21:11:15 2012
@@ -2095,11 +2095,28 @@
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,
Modified: cfe/trunk/test/FixIt/format-darwin.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/format-darwin.m?rev=163772&r1=163771&r2=163772&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/format-darwin.m (original)
+++ cfe/trunk/test/FixIt/format-darwin.m Wed Sep 12 21:11:15 2012
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -fblocks -verify %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -verify %s
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -fblocks -Wformat-non-iso -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -Wformat-non-iso -verify %s
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks %s 2>&1 | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks -Wformat-non-iso %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks -Wformat-non-iso %s 2>&1 | FileCheck %s
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks %s 2>&1 | FileCheck -check-prefix=CHECK-32 %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks %s 2>&1 | FileCheck -check-prefix=CHECK-64 %s
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks -Wformat-non-iso %s 2>&1 | FileCheck -check-prefix=CHECK-32 %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks -Wformat-non-iso %s 2>&1 | FileCheck -check-prefix=CHECK-64 %s
int printf(const char * restrict, ...);
@@ -181,11 +181,18 @@
}
void testCapitals() {
- printf("%D", 1); // no-warning
- printf("%U", 1); // no-warning
- printf("%O", 1); // no-warning
+ printf("%D", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}}
+ printf("%U", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'u'?}}
+ printf("%O", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'o'?}}
- printf("%lD", 1); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
+ // CHECK: fix-it:"{{.*}}":{184:12-184:13}:"d"
+ // CHECK: fix-it:"{{.*}}":{185:12-185:13}:"u"
+ // CHECK: fix-it:"{{.*}}":{186:12-186:13}:"o"
- // CHECK: fix-it:"{{.*}}":{188:11-188:14}:"%D"
+
+ printf("%lD", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}} expected-warning{{format specifies type 'long' but the argument has type 'int'}}
+
+ // FIXME: offering two somewhat-conflicting fixits is less than ideal.
+ // CHECK: fix-it:"{{.*}}":{193:13-193:14}:"d"
+ // CHECK: fix-it:"{{.*}}":{193:11-193:14}:"%D"
}
Modified: cfe/trunk/test/Sema/format-strings-darwin.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-darwin.c?rev=163772&r1=163771&r2=163772&view=diff
==============================================================================
--- cfe/trunk/test/Sema/format-strings-darwin.c (original)
+++ cfe/trunk/test/Sema/format-strings-darwin.c Wed Sep 12 21:11:15 2012
@@ -22,12 +22,12 @@
printf("%O", tooLong);
#ifdef ALLOWED
- // expected-warning at -8 {{'D' conversion specifier is not supported by ISO C}}
- // expected-warning at -8 {{'D' conversion specifier is not supported by ISO C}} expected-warning at -8 {{format specifies type 'int' but the argument has type 'long'}}
- // expected-warning at -8 {{'U' conversion specifier is not supported by ISO C}}
- // expected-warning at -8 {{'U' conversion specifier is not supported by ISO C}} expected-warning at -8 {{format specifies type 'unsigned int' but the argument has type 'long'}}
- // expected-warning at -8 {{'O' conversion specifier is not supported by ISO C}}
- // expected-warning at -8 {{'O' conversion specifier is not supported by ISO C}} expected-warning at -8 {{format specifies type 'unsigned int' but the argument has type 'long'}}
+ // expected-warning at -8 {{'D' conversion specifier is not supported by ISO C}} expected-note at -8 {{did you mean to use 'd'?}}
+ // expected-warning at -8 {{'D' conversion specifier is not supported by ISO C}} expected-note at -8 {{did you mean to use 'd'?}} expected-warning at -8 {{format specifies type 'int' but the argument has type 'long'}}
+ // expected-warning at -8 {{'U' conversion specifier is not supported by ISO C}} expected-note at -8 {{did you mean to use 'u'?}}
+ // expected-warning at -8 {{'U' conversion specifier is not supported by ISO C}} expected-note at -8 {{did you mean to use 'u'?}} expected-warning at -8 {{format specifies type 'unsigned int' but the argument has type 'long'}}
+ // expected-warning at -8 {{'O' conversion specifier is not supported by ISO C}} expected-note at -8 {{did you mean to use 'o'?}}
+ // expected-warning at -8 {{'O' conversion specifier is not supported by ISO C}} expected-note at -8 {{did you mean to use 'o'?}} expected-warning at -8 {{format specifies type 'unsigned int' but the argument has type 'long'}}
#else
// expected-warning at -15 {{invalid conversion specifier 'D'}}
// expected-warning at -15 {{invalid conversion specifier 'D'}}
@@ -40,25 +40,25 @@
#ifdef ALLOWED
void testPrintf(short x, long y) {
- printf("%hD", x); // expected-warning{{conversion specifier is not supported by ISO C}}
- printf("%lD", y); // expected-warning{{conversion specifier is not supported by ISO C}}
- printf("%hU", x); // expected-warning{{conversion specifier is not supported by ISO C}}
- printf("%lU", y); // expected-warning{{conversion specifier is not supported by ISO C}}
- printf("%hO", x); // expected-warning{{conversion specifier is not supported by ISO C}}
- printf("%lO", y); // expected-warning{{conversion specifier is not supported by ISO C}}
+ printf("%hD", x); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}}
+ printf("%lD", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}}
+ printf("%hU", x); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'u'?}}
+ printf("%lU", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'u'?}}
+ printf("%hO", x); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'o'?}}
+ printf("%lO", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'o'?}}
- printf("%+'0.5lD", y); // expected-warning{{conversion specifier is not supported by ISO C}}
- printf("% '0.5lD", y); // expected-warning{{conversion specifier is not supported by ISO C}}
- printf("%#0.5lO", y); // expected-warning{{conversion specifier is not supported by ISO C}}
- printf("%'0.5lU", y); // expected-warning{{conversion specifier is not supported by ISO C}}
+ printf("%+'0.5lD", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}}
+ printf("% '0.5lD", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}}
+ printf("%#0.5lO", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'o'?}}
+ printf("%'0.5lU", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'u'?}}
}
void testScanf(short *x, long *y) {
- scanf("%hD", x); // expected-warning{{conversion specifier is not supported by ISO C}}
- scanf("%lD", y); // expected-warning{{conversion specifier is not supported by ISO C}}
- scanf("%hU", x); // expected-warning{{conversion specifier is not supported by ISO C}}
- scanf("%lU", y); // expected-warning{{conversion specifier is not supported by ISO C}}
- scanf("%hO", x); // expected-warning{{conversion specifier is not supported by ISO C}}
- scanf("%lO", y); // expected-warning{{conversion specifier is not supported by ISO C}}
+ scanf("%hD", x); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}}
+ scanf("%lD", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}}
+ scanf("%hU", x); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'u'?}}
+ scanf("%lU", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'u'?}}
+ scanf("%hO", x); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'o'?}}
+ scanf("%lO", y); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'o'?}}
}
#endif
More information about the cfe-commits
mailing list