Skip to content

Commit fe0d1b6

Browse files
committed
[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
1 parent 422dfea commit fe0d1b6

File tree

2 files changed

+18
-0
lines changed

2 files changed

+18
-0
lines changed

clang/lib/AST/FormatString.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,15 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
748748
case LengthModifier::AsIntMax:
749749
case LengthModifier::AsSizeT:
750750
case LengthModifier::AsPtrDiff:
751+
if (LM.getKind() == LengthModifier::AsSizeT &&
752+
Target.getTriple().isOSMSVCRT() &&
753+
!LO.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
754+
// The standard libraries before MSVC2015 didn't support the 'z' length
755+
// modifier for size_t. So if the MS compatibility version is less than
756+
// that, reject.
757+
return false;
758+
}
759+
751760
switch (CS.getKind()) {
752761
case ConversionSpecifier::dArg:
753762
case ConversionSpecifier::DArg:

clang/test/Sema/format-strings-ms.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 -fms-compatibility-version=18 %s
3+
// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 -fms-compatibility-version=19 -DSIZE_T_OK %s
24
// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 -Wformat-non-iso -DNON_ISO_WARNING %s
35

46
int printf(const char *format, ...) __attribute__((format(printf, 1, 2)));
@@ -85,4 +87,11 @@ void z_test(void *p) {
8587
scanf("%Z", p); // expected-warning{{invalid conversion specifier 'Z'}}
8688
}
8789

90+
void size_t_test(size_t s) {
91+
printf("%zu", s);
92+
#ifndef SIZE_T_OK
93+
// expected-warning@-2 {{length modifier 'z' results in undefined behavior or no effect with 'u' conversion specifier}}
94+
#endif
95+
}
96+
8897
#endif

0 commit comments

Comments
 (0)