mirror of https://github.com/microsoft/clang.git
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@308662 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20dd3343d9
commit
26bc81978d
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 *'}}
|
||||
|
|
Loading…
Reference in New Issue