r188937 - Analysis: Add support for MS specific printf format specifiers

David Majnemer david.majnemer at gmail.com
Wed Aug 21 14:54:46 PDT 2013


Author: majnemer
Date: Wed Aug 21 16:54:46 2013
New Revision: 188937

URL: http://llvm.org/viewvc/llvm-project?rev=188937&view=rev
Log:
Analysis: Add support for MS specific printf format specifiers

Summary: Adds support for %I, %I32 and %I64.

Reviewers: hans, jordan_rose, rnk, majnemer

Reviewed By: majnemer

CC: cfe-commits, cdavis5x

Differential Revision: http://llvm-reviews.chandlerc.com/D1456

Added:
    cfe/trunk/test/Sema/format-strings-ms.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

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=188937&r1=188936&r2=188937&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Wed Aug 21 16:54:46 2013
@@ -73,6 +73,9 @@ public:
     AsIntMax,     // 'j'
     AsSizeT,      // 'z'
     AsPtrDiff,    // 't'
+    AsInt32,      // 'I32' (MSVCRT, like __int32)
+    AsInt3264,    // 'I'   (MSVCRT, like __int3264 from MIDL)
+    AsInt64,      // 'I64' (MSVCRT, like __int64)
     AsLongDouble, // 'L'
     AsAllocate,   // for '%as', GNU extension to C90 scanf
     AsMAllocate,  // for '%ms', GNU extension to scanf
@@ -95,6 +98,9 @@ public:
       case AsLongLong:
       case AsChar:
         return 2;
+      case AsInt32:
+      case AsInt64:
+        return 3;
       case None:
         return 0;
     }

Modified: cfe/trunk/lib/Analysis/FormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=188937&r1=188936&r2=188937&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/FormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/FormatString.cpp Wed Aug 21 16:54:46 2013
@@ -223,6 +223,27 @@ clang::analyze_format_string::ParseLengt
         break;
       }
       return false;
+    // printf: AsInt64, AsInt32, AsInt3264
+    // scanf:  AsInt64
+    case 'I':
+      if (I + 1 != E && I + 2 != E) {
+        if (I[1] == '6' && I[2] == '4') {
+          I += 3;
+          lmKind = LengthModifier::AsInt64;
+          break;
+        }
+        if (IsScanf)
+          return false;
+
+        if (I[1] == '3' && I[2] == '2') {
+          I += 3;
+          lmKind = LengthModifier::AsInt32;
+          break;
+        }
+      }
+      ++I;
+      lmKind = LengthModifier::AsInt3264;
+      break;
   }
   LengthModifier lm(lmPosition, lmKind);
   FS.setLengthModifier(lm);
@@ -471,6 +492,12 @@ analyze_format_string::LengthModifier::t
     return "z";
   case AsPtrDiff:
     return "t";
+  case AsInt32:
+    return "I32";
+  case AsInt3264:
+    return "I";
+  case AsInt64:
+    return "I64";
   case AsLongDouble:
     return "L";
   case AsAllocate:
@@ -514,7 +541,7 @@ const char *ConversionSpecifier::toStrin
   case ScanListArg: return "[";
   case InvalidSpecifier: return NULL;
 
-  // MacOS X unicode extensions.
+  // POSIX unicode extensions.
   case CArg: return "C";
   case SArg: return "S";
 
@@ -678,6 +705,20 @@ bool FormatSpecifier::hasValidLengthModi
         default:
           return false;
       }
+    case LengthModifier::AsInt32:
+    case LengthModifier::AsInt3264:
+    case LengthModifier::AsInt64:
+      switch (CS.getKind()) {
+        case ConversionSpecifier::dArg:
+        case ConversionSpecifier::iArg:
+        case ConversionSpecifier::oArg:
+        case ConversionSpecifier::uArg:
+        case ConversionSpecifier::xArg:
+        case ConversionSpecifier::XArg:
+          return Target.getTriple().isOSMSVCRT();
+        default:
+          return false;
+      }
   }
   llvm_unreachable("Invalid LengthModifier Kind!");
 }
@@ -697,6 +738,9 @@ bool FormatSpecifier::hasStandardLengthM
     case LengthModifier::AsAllocate:
     case LengthModifier::AsMAllocate:
     case LengthModifier::AsQuad:
+    case LengthModifier::AsInt32:
+    case LengthModifier::AsInt3264:
+    case LengthModifier::AsInt64:
       return false;
   }
   llvm_unreachable("Invalid LengthModifier Kind!");

Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=188937&r1=188936&r2=188937&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Wed Aug 21 16:54:46 2013
@@ -187,8 +187,8 @@ static PrintfSpecifierResult ParsePrintf
     case 'i': k = ConversionSpecifier::iArg; break;
     case 'n': k = ConversionSpecifier::nArg; break;
     case 'o': k = ConversionSpecifier::oArg; break;
-    case 'p': k = ConversionSpecifier::pArg;   break;
-    case 's': k = ConversionSpecifier::sArg;      break;
+    case 'p': k = ConversionSpecifier::pArg; break;
+    case 's': k = ConversionSpecifier::sArg; break;
     case 'u': k = ConversionSpecifier::uArg; break;
     case 'x': k = ConversionSpecifier::xArg; break;
     // POSIX specific.
@@ -278,18 +278,26 @@ ArgType PrintfSpecifier::getArgType(ASTC
       case LengthModifier::AsLongDouble:
         // GNU extension.
         return Ctx.LongLongTy;
-      case LengthModifier::None: return Ctx.IntTy;
+      case LengthModifier::None:
+        return Ctx.IntTy;
+      case LengthModifier::AsInt32:
+        return ArgType(Ctx.IntTy, "__int32");
       case LengthModifier::AsChar: return ArgType::AnyCharTy;
       case LengthModifier::AsShort: return Ctx.ShortTy;
       case LengthModifier::AsLong: return Ctx.LongTy;
       case LengthModifier::AsLongLong:
       case LengthModifier::AsQuad:
         return Ctx.LongLongTy;
+      case LengthModifier::AsInt64:
+        return ArgType(Ctx.LongLongTy, "__int64");
       case LengthModifier::AsIntMax:
         return ArgType(Ctx.getIntMaxType(), "intmax_t");
       case LengthModifier::AsSizeT:
         // FIXME: How to get the corresponding signed version of size_t?
         return ArgType();
+      case LengthModifier::AsInt3264:
+        return Ctx.getTargetInfo().getTriple().isArch64Bit() ? Ctx.LongLongTy
+                                                             : Ctx.IntTy;
       case LengthModifier::AsPtrDiff:
         return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
       case LengthModifier::AsAllocate:
@@ -302,17 +310,26 @@ ArgType PrintfSpecifier::getArgType(ASTC
       case LengthModifier::AsLongDouble:
         // GNU extension.
         return Ctx.UnsignedLongLongTy;
-      case LengthModifier::None: return Ctx.UnsignedIntTy;
+      case LengthModifier::None:
+        return Ctx.UnsignedIntTy;
+      case LengthModifier::AsInt32:
+        return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
       case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
       case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
       case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
       case LengthModifier::AsLongLong:
       case LengthModifier::AsQuad:
         return Ctx.UnsignedLongLongTy;
+      case LengthModifier::AsInt64:
+        return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
       case LengthModifier::AsIntMax:
         return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
       case LengthModifier::AsSizeT:
         return ArgType(Ctx.getSizeType(), "size_t");
+      case LengthModifier::AsInt3264:
+        return Ctx.getTargetInfo().getTriple().isArch64Bit()
+                   ? Ctx.UnsignedLongLongTy
+                   : Ctx.UnsignedIntTy;
       case LengthModifier::AsPtrDiff:
         // FIXME: How to get the corresponding unsigned
         // version of ptrdiff_t?
@@ -351,6 +368,9 @@ ArgType PrintfSpecifier::getArgType(ASTC
         return ArgType(); // FIXME: Is this a known extension?
       case LengthModifier::AsAllocate:
       case LengthModifier::AsMAllocate:
+      case LengthModifier::AsInt32:
+      case LengthModifier::AsInt3264:
+      case LengthModifier::AsInt64:
         return ArgType::Invalid();
     }
   }

Modified: cfe/trunk/lib/Analysis/ScanfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=188937&r1=188936&r2=188937&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp Wed Aug 21 16:54:46 2013
@@ -232,6 +232,8 @@ ArgType ScanfSpecifier::getArgType(ASTCo
         case LengthModifier::AsLongLong:
         case LengthModifier::AsQuad:
           return ArgType::PtrTo(Ctx.LongLongTy);
+        case LengthModifier::AsInt64:
+          return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
         case LengthModifier::AsIntMax:
           return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
         case LengthModifier::AsSizeT:
@@ -243,8 +245,9 @@ ArgType ScanfSpecifier::getArgType(ASTCo
           // GNU extension.
           return ArgType::PtrTo(Ctx.LongLongTy);
         case LengthModifier::AsAllocate:
-          return ArgType::Invalid();
         case LengthModifier::AsMAllocate:
+        case LengthModifier::AsInt32:
+        case LengthModifier::AsInt3264:
           return ArgType::Invalid();
       }
 
@@ -267,6 +270,8 @@ ArgType ScanfSpecifier::getArgType(ASTCo
         case LengthModifier::AsLongLong:
         case LengthModifier::AsQuad:
           return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
+        case LengthModifier::AsInt64:
+          return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
         case LengthModifier::AsIntMax:
           return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
         case LengthModifier::AsSizeT:
@@ -278,8 +283,9 @@ ArgType ScanfSpecifier::getArgType(ASTCo
           // GNU extension.
           return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
         case LengthModifier::AsAllocate:
-          return ArgType::Invalid();
         case LengthModifier::AsMAllocate:
+        case LengthModifier::AsInt32:
+        case LengthModifier::AsInt3264:
           return ArgType::Invalid();
       }
 
@@ -349,6 +355,8 @@ ArgType ScanfSpecifier::getArgType(ASTCo
         case LengthModifier::AsLongLong:
         case LengthModifier::AsQuad:
           return ArgType::PtrTo(Ctx.LongLongTy);
+        case LengthModifier::AsInt64:
+          return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
         case LengthModifier::AsIntMax:
           return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
         case LengthModifier::AsSizeT:
@@ -359,6 +367,8 @@ ArgType ScanfSpecifier::getArgType(ASTCo
           return ArgType(); // FIXME: Is this a known extension?
         case LengthModifier::AsAllocate:
         case LengthModifier::AsMAllocate:
+        case LengthModifier::AsInt32:
+        case LengthModifier::AsInt3264:
           return ArgType::Invalid();
         }
 

Added: cfe/trunk/test/Sema/format-strings-ms.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-ms.c?rev=188937&view=auto
==============================================================================
--- cfe/trunk/test/Sema/format-strings-ms.c (added)
+++ cfe/trunk/test/Sema/format-strings-ms.c Wed Aug 21 16:54:46 2013
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 -pedantic %s
+
+int printf(const char *format, ...) __attribute__((format(printf, 1, 2)));
+
+void test() {
+  short val = 30;
+  printf("val = %I64d\n", val); // expected-warning{{'I64' length modifier is not supported by ISO C}} \
+                                // expected-warning{{format specifies type '__int64' (aka 'long long') but the argument has type 'short'}}
+}





More information about the cfe-commits mailing list