[clang] fe0d1b6 - [Clang] Warn about 'z' printf modifier in old MSVC.

Simon Tatham via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 28 01:04:56 PST 2020


Author: Simon Tatham
Date: 2020-01-28T09:04:45Z
New Revision: fe0d1b6a8ac5048b8007e5e7cc2aeb4e3291bda0

URL: https://github.com/llvm/llvm-project/commit/fe0d1b6a8ac5048b8007e5e7cc2aeb4e3291bda0
DIFF: https://github.com/llvm/llvm-project/commit/fe0d1b6a8ac5048b8007e5e7cc2aeb4e3291bda0.diff

LOG: [Clang] Warn about 'z' printf modifier in old MSVC.

Summary:
The 'z' length modifier, signalling that an integer format specifier
takes a `size_t` sized integer, is only supported by the C library of
MSVC 2015 and later. Earlier versions don't recognize the 'z' at all,
and respond to `printf("%zu", x)` by just printing "zu".

So, if the MS compatibility version is set to a value earlier than
MSVC2015, it's useful to warn about 'z' modifiers in printf format
strings we check.

Reviewers: aaron.ballman, lebedev.ri, rnk, majnemer, zturner

Reviewed By: aaron.ballman

Subscribers: amccarth, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D73457

Added: 
    

Modified: 
    clang/lib/AST/FormatString.cpp
    clang/test/Sema/format-strings-ms.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp
index fcc0b3b11e25..2ca8fee67bf0 100644
--- a/clang/lib/AST/FormatString.cpp
+++ b/clang/lib/AST/FormatString.cpp
@@ -748,6 +748,15 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
     case LengthModifier::AsIntMax:
     case LengthModifier::AsSizeT:
     case LengthModifier::AsPtrDiff:
+      if (LM.getKind() == LengthModifier::AsSizeT &&
+          Target.getTriple().isOSMSVCRT() &&
+          !LO.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
+        // The standard libraries before MSVC2015 didn't support the 'z' length
+        // modifier for size_t. So if the MS compatibility version is less than
+        // that, reject.
+        return false;
+      }
+
       switch (CS.getKind()) {
         case ConversionSpecifier::dArg:
         case ConversionSpecifier::DArg:

diff  --git a/clang/test/Sema/format-strings-ms.c b/clang/test/Sema/format-strings-ms.c
index 56a349051d42..c4d3e5664db0 100644
--- a/clang/test/Sema/format-strings-ms.c
+++ b/clang/test/Sema/format-strings-ms.c
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 -fms-compatibility-version=18 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 -fms-compatibility-version=19 -DSIZE_T_OK %s
 // RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 -Wformat-non-iso -DNON_ISO_WARNING %s
 
 int printf(const char *format, ...) __attribute__((format(printf, 1, 2)));
@@ -85,4 +87,11 @@ void z_test(void *p) {
   scanf("%Z", p); // expected-warning{{invalid conversion specifier 'Z'}}
 }
 
+void size_t_test(size_t s) {
+  printf("%zu", s);
+#ifndef SIZE_T_OK
+  // expected-warning at -2 {{length modifier 'z' results in undefined behavior or no effect with 'u' conversion specifier}}
+#endif
+}
+
 #endif


        


More information about the cfe-commits mailing list