summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Shaposhnikov <shal1t712@gmail.com>2017-07-20 20:11:47 +0000
committerAlexander Shaposhnikov <shal1t712@gmail.com>2017-07-20 20:11:47 +0000
commit593e4bbf4ebac52f8a8c69bf804c67affcbb1c69 (patch)
treee5544a29e6afa9593e54b507b8212f6f35b17d87
parentbb76d48d59b2903b15827fdd2b7598e6fcc0cdb8 (diff)
downloadbcm5719-llvm-593e4bbf4ebac52f8a8c69bf804c67affcbb1c69.tar.gz
bcm5719-llvm-593e4bbf4ebac52f8a8c69bf804c67affcbb1c69.zip
[clang] Fix handling of "%zd" in scanf
This diff addresses FIXMEs in lib/Analysis/ScanfFormatString.cpp for the case of ssize_t format specifier and adds tests. In particular, this change enables Clang to emit a warning on incorrect using of "%zd"/"%zn". Test plan: make check-all Differential revision: https://reviews.llvm.org/D35652 llvm-svn: 308662
-rw-r--r--clang/lib/Analysis/ScanfFormatString.cpp5
-rw-r--r--clang/test/Sema/format-strings-fixit-ssize_t.c10
-rw-r--r--clang/test/Sema/format-strings-scanf.c34
3 files changed, 40 insertions, 9 deletions
diff --git a/clang/lib/Analysis/ScanfFormatString.cpp b/clang/lib/Analysis/ScanfFormatString.cpp
index 53422598546..734dc7521c6 100644
--- a/clang/lib/Analysis/ScanfFormatString.cpp
+++ b/clang/lib/Analysis/ScanfFormatString.cpp
@@ -251,8 +251,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsIntMax:
return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
case LengthModifier::AsSizeT:
- // FIXME: ssize_t.
- return ArgType();
+ return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
case LengthModifier::AsPtrDiff:
return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
case LengthModifier::AsLongDouble:
@@ -386,7 +385,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsIntMax:
return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
case LengthModifier::AsSizeT:
- return ArgType(); // FIXME: ssize_t
+ return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
case LengthModifier::AsPtrDiff:
return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
case LengthModifier::AsLongDouble:
diff --git a/clang/test/Sema/format-strings-fixit-ssize_t.c b/clang/test/Sema/format-strings-fixit-ssize_t.c
index 5208a294a48..f8893a14a41 100644
--- a/clang/test/Sema/format-strings-fixit-ssize_t.c
+++ b/clang/test/Sema/format-strings-fixit-ssize_t.c
@@ -1,7 +1,7 @@
// RUN: cp %s %t
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -pedantic -Wall -fixit %t
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -pedantic -Wall -Werror %t
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -E -o - %t | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c99 -pedantic -Wall -fixit %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c99 -fsyntax-only -pedantic -Wall -Werror %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c99 -E -o - %t | FileCheck %s
/* This is a test of the various code modification hints that are
provided as part of warning or extension diagnostics. All of the
@@ -9,10 +9,14 @@
compile cleanly with -Werror -pedantic. */
int printf(char const *, ...);
+int scanf(const char *, ...);
void test() {
typedef signed long int ssize_t;
printf("%f", (ssize_t) 42);
+ ssize_t s;
+ scanf("%f", &s);
}
// CHECK: printf("%zd", (ssize_t) 42);
+// CHECK: scanf("%zd", &s)
diff --git a/clang/test/Sema/format-strings-scanf.c b/clang/test/Sema/format-strings-scanf.c
index 7a92842b245..e700d10618d 100644
--- a/clang/test/Sema/format-strings-scanf.c
+++ b/clang/test/Sema/format-strings-scanf.c
@@ -1,10 +1,18 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral %s
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wformat-nonliteral %s
// Test that -Wformat=0 works:
-// RUN: %clang_cc1 -fsyntax-only -Werror -Wformat=0 %s
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -Werror -Wformat=0 %s
#include <stdarg.h>
-typedef __typeof(sizeof(int)) size_t;
+typedef __SIZE_TYPE__ size_t;
+#define __SSIZE_TYPE__ \
+ __typeof__(_Generic((__SIZE_TYPE__)0, \
+ unsigned long long int : (long long int)0, \
+ unsigned long int : (long int)0, \
+ unsigned int : (int)0, \
+ unsigned short : (short)0, \
+ unsigned char : (signed char)0))
+typedef __SSIZE_TYPE__ ssize_t;
typedef struct _FILE FILE;
typedef __WCHAR_TYPE__ wchar_t;
@@ -172,6 +180,26 @@ void test_qualifiers(const int *cip, volatile int* vip,
scanf("%d", (cip_t)0); // expected-warning{{format specifies type 'int *' but the argument has type 'cip_t' (aka 'const int *')}}
}
+void test_size_types() {
+ size_t s = 0;
+ scanf("%zu", &s); // No warning.
+
+ double d1 = 0.;
+ scanf("%zu", &d1); // expected-warning-re{{format specifies type 'size_t *' (aka '{{.+}}') but the argument has type 'double *'}}
+
+ ssize_t ss = 0;
+ scanf("%zd", &s); // No warning.
+
+ double d2 = 0.;
+ scanf("%zd", &d2); // expected-warning-re{{format specifies type 'ssize_t *' (aka '{{.+}}') but the argument has type 'double *'}}
+
+ ssize_t sn = 0;
+ scanf("%zn", &sn); // No warning.
+
+ double d3 = 0.;
+ scanf("%zn", &d3); // expected-warning-re{{format specifies type 'ssize_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 *'}}
OpenPOWER on IntegriCloud