r308662 - [clang] Fix handling of "%zd" in scanf

Alexander Shaposhnikov via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 20 13:11:47 PDT 2017


Author: alexshap
Date: Thu Jul 20 13:11:47 2017
New Revision: 308662

URL: http://llvm.org/viewvc/llvm-project?rev=308662&view=rev
Log:
[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

Modified:
    cfe/trunk/lib/Analysis/ScanfFormatString.cpp
    cfe/trunk/test/Sema/format-strings-fixit-ssize_t.c
    cfe/trunk/test/Sema/format-strings-scanf.c

Modified: cfe/trunk/lib/Analysis/ScanfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=308662&r1=308661&r2=308662&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp Thu Jul 20 13:11:47 2017
@@ -251,8 +251,7 @@ ArgType ScanfSpecifier::getArgType(ASTCo
         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(ASTCo
         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:

Modified: cfe/trunk/test/Sema/format-strings-fixit-ssize_t.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-fixit-ssize_t.c?rev=308662&r1=308661&r2=308662&view=diff
==============================================================================
--- cfe/trunk/test/Sema/format-strings-fixit-ssize_t.c (original)
+++ cfe/trunk/test/Sema/format-strings-fixit-ssize_t.c Thu Jul 20 13:11:47 2017
@@ -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)

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=308662&r1=308661&r2=308662&view=diff
==============================================================================
--- cfe/trunk/test/Sema/format-strings-scanf.c (original)
+++ cfe/trunk/test/Sema/format-strings-scanf.c Thu Jul 20 13:11:47 2017
@@ -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, vol
   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 *'}}




More information about the cfe-commits mailing list