[cfe-commits] r163771 - in /cfe/trunk: include/clang/Analysis/Analyses/FormatString.h lib/Analysis/FormatString.cpp lib/Analysis/PrintfFormatString.cpp lib/Analysis/ScanfFormatString.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:04 PDT 2012
Author: jrose
Date: Wed Sep 12 21:11:03 2012
New Revision: 163771
URL: http://llvm.org/viewvc/llvm-project?rev=163771&view=rev
Log:
Format strings: %D, %U, and %O are valid on Darwin (same as %d, %u, %o).
These will warn under -Wformat-non-iso, and will still be rejected
outright on other platforms.
<rdar://problem/12061922>
Added:
cfe/trunk/test/Sema/format-strings-darwin.c
Modified:
cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
cfe/trunk/lib/Analysis/FormatString.cpp
cfe/trunk/lib/Analysis/PrintfFormatString.cpp
cfe/trunk/lib/Analysis/ScanfFormatString.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/test/FixIt/format-darwin.m
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=163771&r1=163770&r2=163771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Wed Sep 12 21:11:03 2012
@@ -117,11 +117,14 @@
// C99 conversion specifiers.
cArg,
dArg,
+ DArg, // Apple extension
iArg,
IntArgBeg = dArg, IntArgEnd = iArg,
oArg,
+ OArg, // Apple extension
uArg,
+ UArg, // Apple extension
xArg,
XArg,
UIntArgBeg = oArg, UIntArgEnd = XArg,
@@ -628,10 +631,12 @@
};
bool ParsePrintfString(FormatStringHandler &H,
- const char *beg, const char *end, const LangOptions &LO);
+ const char *beg, const char *end, const LangOptions &LO,
+ const TargetInfo &Target);
bool ParseScanfString(FormatStringHandler &H,
- const char *beg, const char *end, const LangOptions &LO);
+ const char *beg, const char *end, const LangOptions &LO,
+ const TargetInfo &Target);
} // end analyze_format_string namespace
} // end clang namespace
Modified: cfe/trunk/lib/Analysis/FormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=163771&r1=163770&r2=163771&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/FormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/FormatString.cpp Wed Sep 12 21:11:03 2012
@@ -490,9 +490,12 @@
const char *ConversionSpecifier::toString() const {
switch (kind) {
case dArg: return "d";
+ case DArg: return "D";
case iArg: return "i";
case oArg: return "o";
+ case OArg: return "O";
case uArg: return "u";
+ case UArg: return "U";
case xArg: return "x";
case XArg: return "X";
case fArg: return "f";
@@ -564,9 +567,12 @@
case LengthModifier::AsPtrDiff:
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
+ case ConversionSpecifier::DArg:
case ConversionSpecifier::iArg:
case ConversionSpecifier::oArg:
+ case ConversionSpecifier::OArg:
case ConversionSpecifier::uArg:
+ case ConversionSpecifier::UArg:
case ConversionSpecifier::xArg:
case ConversionSpecifier::XArg:
case ConversionSpecifier::nArg:
@@ -579,9 +585,12 @@
case LengthModifier::AsLong:
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
+ case ConversionSpecifier::DArg:
case ConversionSpecifier::iArg:
case ConversionSpecifier::oArg:
+ case ConversionSpecifier::OArg:
case ConversionSpecifier::uArg:
+ case ConversionSpecifier::UArg:
case ConversionSpecifier::xArg:
case ConversionSpecifier::XArg:
case ConversionSpecifier::aArg:
@@ -699,6 +708,9 @@
return LangOpt.ObjC1 || LangOpt.ObjC2;
case ConversionSpecifier::InvalidSpecifier:
case ConversionSpecifier::PrintErrno:
+ case ConversionSpecifier::DArg:
+ case ConversionSpecifier::OArg:
+ case ConversionSpecifier::UArg:
return false;
}
llvm_unreachable("Invalid ConversionSpecifier Kind!");
Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=163771&r1=163770&r2=163771&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Wed Sep 12 21:11:03 2012
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Basic/TargetInfo.h"
#include "FormatStringParsing.h"
using clang::analyze_format_string::ArgType;
@@ -52,7 +53,8 @@
const char *&Beg,
const char *E,
unsigned &argIndex,
- const LangOptions &LO) {
+ const LangOptions &LO,
+ const TargetInfo &Target) {
using namespace clang::analyze_format_string;
using namespace clang::analyze_printf;
@@ -196,6 +198,19 @@
case '@': k = ConversionSpecifier::ObjCObjArg; break;
// Glibc specific.
case 'm': k = ConversionSpecifier::PrintErrno; break;
+ // Apple-specific
+ case 'D':
+ if (Target.getTriple().isOSDarwin())
+ k = ConversionSpecifier::DArg;
+ break;
+ case 'O':
+ if (Target.getTriple().isOSDarwin())
+ k = ConversionSpecifier::OArg;
+ break;
+ case 'U':
+ if (Target.getTriple().isOSDarwin())
+ k = ConversionSpecifier::UArg;
+ break;
}
PrintfConversionSpecifier CS(conversionPosition, k);
FS.setConversionSpecifier(CS);
@@ -212,14 +227,15 @@
bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
const char *I,
const char *E,
- const LangOptions &LO) {
+ const LangOptions &LO,
+ const TargetInfo &Target) {
unsigned argIndex = 0;
// Keep looking for a format specifier until we have exhausted the string.
while (I != E) {
const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
- LO);
+ LO, Target);
// Did a fail-stop error of any kind occur when parsing the specifier?
// If so, don't do any more processing.
if (FSR.shouldStop())
@@ -551,6 +567,7 @@
// The plus prefix only makes sense for signed conversions
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
+ case ConversionSpecifier::DArg:
case ConversionSpecifier::iArg:
case ConversionSpecifier::fArg:
case ConversionSpecifier::FArg:
@@ -574,6 +591,7 @@
// Alternate form flag only valid with the oxXaAeEfFgG conversions
switch (CS.getKind()) {
case ConversionSpecifier::oArg:
+ case ConversionSpecifier::OArg:
case ConversionSpecifier::xArg:
case ConversionSpecifier::XArg:
case ConversionSpecifier::aArg:
@@ -598,9 +616,12 @@
// Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
+ case ConversionSpecifier::DArg:
case ConversionSpecifier::iArg:
case ConversionSpecifier::oArg:
+ case ConversionSpecifier::OArg:
case ConversionSpecifier::uArg:
+ case ConversionSpecifier::UArg:
case ConversionSpecifier::xArg:
case ConversionSpecifier::XArg:
case ConversionSpecifier::aArg:
@@ -625,6 +646,7 @@
// The space prefix only makes sense for signed conversions
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
+ case ConversionSpecifier::DArg:
case ConversionSpecifier::iArg:
case ConversionSpecifier::fArg:
case ConversionSpecifier::FArg:
@@ -661,8 +683,10 @@
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
+ case ConversionSpecifier::DArg:
case ConversionSpecifier::iArg:
case ConversionSpecifier::uArg:
+ case ConversionSpecifier::UArg:
case ConversionSpecifier::fArg:
case ConversionSpecifier::FArg:
case ConversionSpecifier::gArg:
@@ -680,9 +704,12 @@
// Precision is only valid with the diouxXaAeEfFgGs conversions
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
+ case ConversionSpecifier::DArg:
case ConversionSpecifier::iArg:
case ConversionSpecifier::oArg:
+ case ConversionSpecifier::OArg:
case ConversionSpecifier::uArg:
+ case ConversionSpecifier::UArg:
case ConversionSpecifier::xArg:
case ConversionSpecifier::XArg:
case ConversionSpecifier::aArg:
Modified: cfe/trunk/lib/Analysis/ScanfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=163771&r1=163770&r2=163771&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp Wed Sep 12 21:11:03 2012
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Basic/TargetInfo.h"
#include "FormatStringParsing.h"
using clang::analyze_format_string::ArgType;
@@ -67,7 +68,8 @@
const char *&Beg,
const char *E,
unsigned &argIndex,
- const LangOptions &LO) {
+ const LangOptions &LO,
+ const TargetInfo &Target) {
using namespace clang::analyze_scanf;
const char *I = Beg;
@@ -172,6 +174,20 @@
case 'o': k = ConversionSpecifier::oArg; break;
case 's': k = ConversionSpecifier::sArg; break;
case 'p': k = ConversionSpecifier::pArg; break;
+ // Apple extensions
+ // Apple-specific
+ case 'D':
+ if (Target.getTriple().isOSDarwin())
+ k = ConversionSpecifier::DArg;
+ break;
+ case 'O':
+ if (Target.getTriple().isOSDarwin())
+ k = ConversionSpecifier::OArg;
+ break;
+ case 'U':
+ if (Target.getTriple().isOSDarwin())
+ k = ConversionSpecifier::UArg;
+ break;
}
ScanfConversionSpecifier CS(conversionPosition, k);
if (k == ScanfConversionSpecifier::ScanListArg) {
@@ -202,6 +218,7 @@
switch(CS.getKind()) {
// Signed int.
case ConversionSpecifier::dArg:
+ case ConversionSpecifier::DArg:
case ConversionSpecifier::iArg:
switch (LM.getKind()) {
case LengthModifier::None:
@@ -233,7 +250,9 @@
// Unsigned int.
case ConversionSpecifier::oArg:
+ case ConversionSpecifier::OArg:
case ConversionSpecifier::uArg:
+ case ConversionSpecifier::UArg:
case ConversionSpecifier::xArg:
case ConversionSpecifier::XArg:
switch (LM.getKind()) {
@@ -465,14 +484,15 @@
bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
const char *I,
const char *E,
- const LangOptions &LO) {
+ const LangOptions &LO,
+ const TargetInfo &Target) {
unsigned argIndex = 0;
// Keep looking for a format specifier until we have exhausted the string.
while (I != E) {
const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
- LO);
+ LO, Target);
// Did a fail-stop error of any kind occur when parsing the specifier?
// If so, don't do any more processing.
if (FSR.shouldStop())
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=163771&r1=163770&r2=163771&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Sep 12 21:11:03 2012
@@ -3020,7 +3020,8 @@
inFunctionCall, CallType);
if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen,
- getLangOpts()))
+ getLangOpts(),
+ Context.getTargetInfo()))
H.DoneProcessing();
} else if (Type == FST_Scanf) {
CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs,
@@ -3028,7 +3029,8 @@
inFunctionCall, CallType);
if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen,
- getLangOpts()))
+ getLangOpts(),
+ Context.getTargetInfo()))
H.DoneProcessing();
} // TODO: handle other formats
}
Modified: cfe/trunk/test/FixIt/format-darwin.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/format-darwin.m?rev=163771&r1=163770&r2=163771&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/format-darwin.m (original)
+++ cfe/trunk/test/FixIt/format-darwin.m Wed Sep 12 21:11:03 2012
@@ -179,3 +179,13 @@
// CHECK: fix-it:"{{.*}}":{168:11-168:13}:"%u"
// CHECK: fix-it:"{{.*}}":{168:16-168:24}:"(unsigned int)"
}
+
+void testCapitals() {
+ printf("%D", 1); // no-warning
+ printf("%U", 1); // no-warning
+ printf("%O", 1); // no-warning
+
+ printf("%lD", 1); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
+
+ // CHECK: fix-it:"{{.*}}":{188:11-188:14}:"%D"
+}
Added: cfe/trunk/test/Sema/format-strings-darwin.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-darwin.c?rev=163771&view=auto
==============================================================================
--- cfe/trunk/test/Sema/format-strings-darwin.c (added)
+++ cfe/trunk/test/Sema/format-strings-darwin.c Wed Sep 12 21:11:03 2012
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple i386-apple-darwin9 -pedantic -DALLOWED %s
+// RUN: %clang_cc1 -fsyntax-only -verify -triple thumbv6-apple-ios4.0 -pedantic -DALLOWED %s
+
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-mingw32 -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-pc-win32 -pedantic %s
+
+// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-linux-gnu -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-unknown-freebsd -pedantic %s
+
+int printf(const char *restrict, ...);
+int scanf(const char * restrict, ...) ;
+
+void test() {
+ int justRight = 1;
+ long tooLong = 2;
+
+ printf("%D", justRight);
+ printf("%D", tooLong);
+ printf("%U", justRight);
+ printf("%U", tooLong);
+ printf("%O", justRight);
+ 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'}}
+#else
+ // expected-warning at -15 {{invalid conversion specifier 'D'}}
+ // expected-warning at -15 {{invalid conversion specifier 'D'}}
+ // expected-warning at -15 {{invalid conversion specifier 'U'}}
+ // expected-warning at -15 {{invalid conversion specifier 'U'}}
+ // expected-warning at -15 {{invalid conversion specifier 'O'}}
+ // expected-warning at -15 {{invalid conversion specifier 'O'}}
+#endif
+}
+
+#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("%+'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}}
+}
+
+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}}
+}
+#endif
More information about the cfe-commits
mailing list