teak-llvm/clang/test/SemaObjC/format-size-spec-nsinteger.m
Alex Lorenz b2043ac72a [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin
The '%tu'/'%td' as formatting specifiers have been used to print out the
NSInteger/NSUInteger values for a long time. Typically their ABI matches, but that's
not the case on watchOS. The ABI difference boils down to the following:

- Regular 32-bit darwin targets (like armv7) use 'ptrdiff_t' of type 'int',
  which matches 'NSInteger'.
- WatchOS arm target (armv7k) uses 'ptrdiff_t' of type 'long', which doesn't
  match 'NSInteger' of type 'int'.

Because of this ABI difference these specifiers trigger -Wformat warnings only
for watchOS builds, which is really inconvenient for cross-platform code.

This patch avoids this -Wformat warning for '%tu'/'%td' and NS[U]Integer only,
and instead uses the new -Wformat-pedantic warning that JF introduced in
https://reviews.llvm.org/D47290. This is acceptable because Darwin guarantees that,
despite the watchOS ABI differences, sizeof(ptrdiff_t) == sizeof(NS[U]Integer),
and alignof(ptrdiff_t) == alignof(NS[U]Integer) so the warning is therefore noisy
for pedantic reasons.

I'll update public documentation to ensure that this behaviour is properly
communicated.

rdar://41739204

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

llvm-svn: 336396
2018-07-05 22:51:11 +00:00

53 lines
1.8 KiB
Objective-C

// RUN: %clang_cc1 -triple thumbv7-apple-ios -Wno-objc-root-class -fsyntax-only -verify -Wformat %s
// RUN: %clang_cc1 -triple thumbv7-apple-ios -Wno-objc-root-class -fsyntax-only -verify -Wformat-pedantic -DPEDANTIC %s
// RUN: %clang_cc1 -triple thumbv7k-apple-watchos2.0.0 -fsyntax-only -fblocks -verify %s
// RUN: %clang_cc1 -triple thumbv7k-apple-watchos2.0.0 -fsyntax-only -fblocks -verify -Wformat-pedantic -DPEDANTIC %s
#if !defined(PEDANTIC)
// expected-no-diagnostics
#endif
#if __LP64__
typedef unsigned long NSUInteger;
typedef long NSInteger;
typedef long ptrdiff_t;
#else
typedef unsigned int NSUInteger;
typedef int NSInteger;
#if __is_target_os(watchos)
// Watch ABI uses long for ptrdiff_t.
typedef long ptrdiff_t;
#else
typedef int ptrdiff_t;
#endif
#endif
@class NSString;
extern void NSLog(NSString *format, ...);
void testSizeSpecifier() {
NSInteger i = 0;
NSUInteger j = 0;
NSLog(@"max NSInteger = %zi", i);
NSLog(@"max NSUinteger = %zu", j);
#if defined(PEDANTIC)
// expected-warning@-4 {{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}
// expected-warning@-4 {{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}
#endif
}
void testPtrdiffSpecifier(ptrdiff_t x) {
NSInteger i = 0;
NSUInteger j = 0;
NSLog(@"ptrdiff_t NSUinteger: %tu", j);
NSLog(@"ptrdiff_t NSInteger: %td", i);
NSLog(@"ptrdiff_t %tu, %td", x, x);
#if __is_target_os(watchos) && defined(PEDANTIC)
// expected-warning@-4 {{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}
// expected-warning@-4 {{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}
#endif
}