forked from OSchip/llvm-project
[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
This commit is contained in:
parent
422dfea577
commit
fe0d1b6a8a
|
@ -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:
|
||||
|
|
|
@ -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@-2 {{length modifier 'z' results in undefined behavior or no effect with 'u' conversion specifier}}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue