From 29e97cb35fab314388f62b68fefa78947e93c1dc Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 27 Oct 2011 08:29:09 +0000 Subject: [PATCH] Teach format string analysis that "%zu" means size_t. 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 | 10 +++++++++- lib/AST/ASTContext.cpp | 12 +++++++++++- lib/Analysis/PrintfFormatString.cpp | 14 +++++--------- test/Sema/format-strings-size_t.c | 15 +++++++++++++++ 4 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 test/Sema/format-strings-size_t.c diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index a8590b2983..0a608707d5 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -835,6 +835,14 @@ public: /// in . 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 . + CanQualType getIntMaxType() const; + + /// getUIntMaxType - Return the unique type for "uintmax_t" (C99 7.18.1.5), + /// defined in . + 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 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 . Pointer - pointer requires this (C99 6.5.6p9). QualType getPointerDiffType() const; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index cb4e09bfc9..b695a5b709 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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 . Pointer - pointer requires this (C99 6.5.6p9). QualType ASTContext::getPointerDiffType() const { return getFromTargetType(Target->getPtrDiffType(0)); diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index 7347dca3c2..70dbfd30ce 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -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 index 0000000000..c86a9e4428 --- /dev/null +++ b/test/Sema/format-strings-size_t.c @@ -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''}} +} -- 2.40.0