[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
diff --git a/clang/test/SemaObjC/format-size-spec-nsinteger.m b/clang/test/SemaObjC/format-size-spec-nsinteger.m
index 9eb954e..e7c0a0d 100644
--- a/clang/test/SemaObjC/format-size-spec-nsinteger.m
+++ b/clang/test/SemaObjC/format-size-spec-nsinteger.m
@@ -1,5 +1,7 @@
 // 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
@@ -8,9 +10,16 @@
 #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;
@@ -28,3 +37,16 @@
   // 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
+}