Skip to content

Commit

Permalink
Teach format string analysis that "%zu" means size_t.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
zmodem committed Oct 27, 2011
1 parent 98a9203 commit 29e97cb
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 11 deletions.
10 changes: 9 additions & 1 deletion include/clang/AST/ASTContext.h
Expand Up @@ -835,6 +835,14 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// 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.
Expand All @@ -848,7 +856,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// 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;

Expand Down
12 changes: 11 additions & 1 deletion lib/AST/ASTContext.cpp
Expand Up @@ -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 {
Expand All @@ -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));
Expand Down
14 changes: 5 additions & 9 deletions lib/Analysis/PrintfFormatString.cpp
Expand Up @@ -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();
}

Expand All @@ -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?
Expand Down
15 changes: 15 additions & 0 deletions 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''}}
}

0 comments on commit 29e97cb

Please sign in to comment.