r314470 - [clang] Add getUnsignedPointerDiffType method
Alexander Shaposhnikov via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 28 16:11:31 PDT 2017
Author: alexshap
Date: Thu Sep 28 16:11:31 2017
New Revision: 314470
URL: http://llvm.org/viewvc/llvm-project?rev=314470&view=rev
Log:
[clang] Add getUnsignedPointerDiffType method
C11 standard refers to the unsigned counterpart of the type ptrdiff_t
in the paragraph 7.21.6.1p7 where it defines the format specifier %tu.
In Clang (in PrintfFormatString.cpp, lines 508-510) there is a FIXME for this case,
in particular, Clang didn't diagnose %tu issues at all, i.e.
it didn't emit any warnings on the code printf("%tu", 3.14).
In this diff we add a method getUnsignedPointerDiffType for getting the corresponding type
similarly to how it's already done in the other analogous cases (size_t, ssize_t, ptrdiff_t etc)
and fix -Wformat diagnostics for %tu plus the emitted fix-it as well.
Test plan: make check-all
Differential revision: https://reviews.llvm.org/D38270
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/Basic/TargetInfo.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/Analysis/PrintfFormatString.cpp
cfe/trunk/lib/Analysis/ScanfFormatString.cpp
cfe/trunk/test/FixIt/format.m
cfe/trunk/test/Sema/format-strings-scanf.c
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=314470&r1=314469&r2=314470&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Sep 28 16:11:31 2017
@@ -1489,6 +1489,11 @@ public:
/// <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType getPointerDiffType() const;
+ /// \brief Return the unique unsigned counterpart of "ptrdiff_t"
+ /// integer type. The standard (C11 7.21.6.1p7) refers to this type
+ /// in the definition of %tu format specifier.
+ QualType getUnsignedPointerDiffType() const;
+
/// \brief Return the unique type for "pid_t" defined in
/// <sys/types.h>. We need this to compute the correct type for vfork().
QualType getProcessIDType() const;
Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=314470&r1=314469&r2=314470&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Thu Sep 28 16:11:31 2017
@@ -248,6 +248,9 @@ public:
IntType getPtrDiffType(unsigned AddrSpace) const {
return AddrSpace == 0 ? PtrDiffType : getPtrDiffTypeV(AddrSpace);
}
+ IntType getUnsignedPtrDiffType(unsigned AddrSpace) const {
+ return getCorrespondingUnsignedType(getPtrDiffType(AddrSpace));
+ }
IntType getIntPtrType() const { return IntPtrType; }
IntType getUIntPtrType() const {
return getCorrespondingUnsignedType(IntPtrType);
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=314470&r1=314469&r2=314470&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Sep 28 16:11:31 2017
@@ -4571,6 +4571,13 @@ QualType ASTContext::getPointerDiffType(
return getFromTargetType(Target->getPtrDiffType(0));
}
+/// \brief Return the unique unsigned counterpart of "ptrdiff_t"
+/// integer type. The standard (C11 7.21.6.1p7) refers to this type
+/// in the definition of %tu format specifier.
+QualType ASTContext::getUnsignedPointerDiffType() const {
+ return getFromTargetType(Target->getUnsignedPtrDiffType(0));
+}
+
/// \brief Return the unique type for "pid_t" defined in
/// <sys/types.h>. We need this to compute the correct type for vfork().
QualType ASTContext::getProcessIDType() const {
Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=314470&r1=314469&r2=314470&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Thu Sep 28 16:11:31 2017
@@ -505,9 +505,7 @@ ArgType PrintfSpecifier::getArgType(ASTC
? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
: ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
case LengthModifier::AsPtrDiff:
- // FIXME: How to get the corresponding unsigned
- // version of ptrdiff_t?
- return ArgType();
+ return ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t");
case LengthModifier::AsAllocate:
case LengthModifier::AsMAllocate:
case LengthModifier::AsWide:
Modified: cfe/trunk/lib/Analysis/ScanfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=314470&r1=314469&r2=314470&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp Thu Sep 28 16:11:31 2017
@@ -291,8 +291,8 @@ ArgType ScanfSpecifier::getArgType(ASTCo
case LengthModifier::AsSizeT:
return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
case LengthModifier::AsPtrDiff:
- // FIXME: Unsigned version of ptrdiff_t?
- return ArgType();
+ return ArgType::PtrTo(
+ ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
case LengthModifier::AsLongDouble:
// GNU extension.
return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
Modified: cfe/trunk/test/FixIt/format.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/format.m?rev=314470&r1=314469&r2=314470&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/format.m (original)
+++ cfe/trunk/test/FixIt/format.m Thu Sep 28 16:11:31 2017
@@ -242,6 +242,37 @@ void testSizeTypes() {
// see the comment in PrintfSpecifier::fixType in PrintfFormatString.cpp.
}
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+#define __UNSIGNED_PTRDIFF_TYPE__ \
+ __typeof__(_Generic((__PTRDIFF_TYPE__)0, \
+ long long int : (unsigned long long int)0, \
+ long int : (unsigned long int)0, \
+ int : (unsigned int)0, \
+ short : (unsigned short)0, \
+ signed char : (unsigned char)0))
+
+void testPtrDiffTypes() {
+ __UNSIGNED_PTRDIFF_TYPE__ p1 = 0;
+ printf("%tu", p1); // No warning.
+
+ printf("%tu", 0.f); // expected-warning-re{{format specifies type 'unsigned ptrdiff_t' (aka '{{.+}}') but the argument has type 'float'}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%f"
+
+ ptrdiff_t p2 = 0;
+ printf("%td", p2); // No warning.
+
+ printf("%td", 0.f); // expected-warning-re{{format specifies type 'ptrdiff_t' (aka '{{.+}}') but the argument has type 'float'}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%f"
+
+ ptrdiff_t p3 = 0;
+ printf("%tn", &p3); // No warning.
+
+ short x;
+ printf("%tn", &x); // expected-warning-re{{format specifies type 'ptrdiff_t *' (aka '{{.+}}') but the argument has type 'short *'}}
+ // PrintfSpecifier::fixType doesn't handle %n, so a fix-it is not emitted,
+ // see the comment in PrintfSpecifier::fixType in PrintfFormatString.cpp.
+}
+
void testEnum() {
typedef enum {
ImplicitA = 1,
Modified: cfe/trunk/test/Sema/format-strings-scanf.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-scanf.c?rev=314470&r1=314469&r2=314470&view=diff
==============================================================================
--- cfe/trunk/test/Sema/format-strings-scanf.c (original)
+++ cfe/trunk/test/Sema/format-strings-scanf.c Thu Sep 28 16:11:31 2017
@@ -13,6 +13,16 @@ typedef __SIZE_TYPE__ size_t;
unsigned short : (short)0, \
unsigned char : (signed char)0))
typedef __SSIZE_TYPE__ ssize_t;
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+#define __UNSIGNED_PTRDIFF_TYPE__ \
+ __typeof__(_Generic((__PTRDIFF_TYPE__)0, \
+ long long int : (unsigned long long int)0, \
+ long int : (unsigned long int)0, \
+ int : (unsigned int)0, \
+ short : (unsigned short)0, \
+ signed char : (unsigned char)0))
+
typedef struct _FILE FILE;
typedef __WCHAR_TYPE__ wchar_t;
@@ -200,6 +210,26 @@ void test_size_types() {
scanf("%zn", &d3); // expected-warning-re{{format specifies type 'ssize_t *' (aka '{{.+}}') but the argument has type 'double *'}}
}
+void test_ptrdiff_t_types() {
+ __UNSIGNED_PTRDIFF_TYPE__ p1 = 0;
+ scanf("%tu", &p1); // No warning.
+
+ double d1 = 0.;
+ scanf("%tu", &d1); // expected-warning-re{{format specifies type 'unsigned ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}
+
+ ptrdiff_t p2 = 0;
+ scanf("%td", &p2); // No warning.
+
+ double d2 = 0.;
+ scanf("%td", &d2); // expected-warning-re{{format specifies type 'ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}
+
+ ptrdiff_t p3 = 0;
+ scanf("%tn", &p3); // No warning.
+
+ double d3 = 0.;
+ scanf("%tn", &d3); // expected-warning-re{{format specifies type 'ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}
+}
+
void check_conditional_literal(char *s, int *i) {
scanf(0 ? "%s" : "%d", i); // no warning
scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char *'}}
More information about the cfe-commits
mailing list