]> granicus.if.org Git - clang/commitdiff
Teach format string analysis that "%zu" means size_t.
authorHans Wennborg <hans@hanshq.net>
Thu, 27 Oct 2011 08:29:09 +0000 (08:29 +0000)
committerHans Wennborg <hans@hanshq.net>
Thu, 27 Oct 2011 08:29:09 +0000 (08:29 +0000)
The code had it backwards, thinking size_t was signed, and using that for "%zd".

Also let the analysis get the types for (u)intmax_t while we are at it.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143099 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
lib/Analysis/PrintfFormatString.cpp
test/Sema/format-strings-size_t.c [new file with mode: 0644]

index a8590b29836a7ef95b11accfa33e62599d73dc73..0a608707d545e51ac527b36f2d3e3b8f8c688fb7 100644 (file)
@@ -835,6 +835,14 @@ public:
   /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
   CanQualType getSizeType() const;
 
+  /// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5),
+  /// defined in <stdint.h>.
+  CanQualType getIntMaxType() const;
+
+  /// getUIntMaxType - Return the unique type for "uintmax_t" (C99 7.18.1.5),
+  /// defined in <stdint.h>.
+  CanQualType getUIntMaxType() const;
+
   /// getWCharType - In C++, this returns the unique wchar_t type.  In C99, this
   /// returns a type compatible with the type defined in <stddef.h> as defined
   /// by the target.
@@ -848,7 +856,7 @@ public:
   /// Used when in C++, as a GCC extension.
   QualType getUnsignedWCharType() const;
 
-  /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
+  /// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
   /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
   QualType getPointerDiffType() const;
 
index cb4e09bfc9eacbe5377ea5e2a033ca1f3f4c66c5..b695a5b7095888fa640a3910533efa7974610925 100644 (file)
@@ -3001,6 +3001,16 @@ CanQualType ASTContext::getSizeType() const {
   return getFromTargetType(Target->getSizeType());
 }
 
+/// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5).
+CanQualType ASTContext::getIntMaxType() const {
+  return getFromTargetType(Target->getIntMaxType());
+}
+
+/// getUIntMaxType - Return the unique type for "uintmax_t" (C99 7.18.1.5).
+CanQualType ASTContext::getUIntMaxType() const {
+  return getFromTargetType(Target->getUIntMaxType());
+}
+
 /// getSignedWCharType - Return the type of "signed wchar_t".
 /// Used when in C++, as a GCC extension.
 QualType ASTContext::getSignedWCharType() const {
@@ -3015,7 +3025,7 @@ QualType ASTContext::getUnsignedWCharType() const {
   return UnsignedIntTy;
 }
 
-/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
+/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
 /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
 QualType ASTContext::getPointerDiffType() const {
   return getFromTargetType(Target->getPtrDiffType(0));
index 7347dca3c21e3024ba56a764a945e07d86fb1e7e..70dbfd30ceefd56b2a5c3dcfd1b7833c9375013d 100644 (file)
@@ -301,10 +301,10 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
       case LengthModifier::AsShort: return Ctx.ShortTy;
       case LengthModifier::AsLong: return Ctx.LongTy;
       case LengthModifier::AsLongLong: return Ctx.LongLongTy;
-      case LengthModifier::AsIntMax:
-        // FIXME: Return unknown for now.
+      case LengthModifier::AsIntMax: return Ctx.getIntMaxType();
+      case LengthModifier::AsSizeT:
+        // FIXME: How to get the corresponding signed version of size_t?
         return ArgTypeResult();
-      case LengthModifier::AsSizeT: return Ctx.getSizeType();
       case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType();
     }
 
@@ -317,13 +317,9 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
       case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
       case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
       case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy;
-      case LengthModifier::AsIntMax:
-        // FIXME: Return unknown for now.
-        return ArgTypeResult();
+      case LengthModifier::AsIntMax: return Ctx.getUIntMaxType();
       case LengthModifier::AsSizeT:
-        // FIXME: How to get the corresponding unsigned
-        // version of size_t?
-        return ArgTypeResult();
+        return Ctx.getSizeType();
       case LengthModifier::AsPtrDiff:
         // FIXME: How to get the corresponding unsigned
         // version of ptrdiff_t?
diff --git a/test/Sema/format-strings-size_t.c b/test/Sema/format-strings-size_t.c
new file mode 100644 (file)
index 0000000..c86a9e4
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s
+
+int printf(char const *, ...);
+
+void test(void) {
+  // size_t
+  printf("%zu", (double)42); // expected-warning {{conversion specifies type 'unsigned long' but the argument has type 'double''}}
+
+  // intmax_t / uintmax_t
+  printf("%jd", (double)42); // expected-warning {{conversion specifies type 'long' but the argument has type 'double''}}
+  printf("%ju", (double)42); // expected-warning {{conversion specifies type 'unsigned long' but the argument has type 'double''}}
+
+  // ptrdiff_t
+  printf("%td", (double)42); // expected-warning {{conversion specifies type 'long' but the argument has type 'double''}}
+}