[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