[PATCH] D48852: [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin
This revision was automatically updated to reflect the committed changes. Closed by commit rC336396: [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin (authored by arphaman, committed by ). Repository: rC Clang https://reviews.llvm.org/D48852 Files: include/clang/Analysis/Analyses/FormatString.h lib/Analysis/PrintfFormatString.cpp lib/Sema/SemaChecking.cpp test/SemaObjC/format-size-spec-nsinteger.m Index: include/clang/Analysis/Analyses/FormatString.h === --- include/clang/Analysis/Analyses/FormatString.h +++ include/clang/Analysis/Analyses/FormatString.h @@ -257,7 +257,12 @@ const Kind K; QualType T; const char *Name = nullptr; - bool Ptr = false, IsSizeT = false; + bool Ptr = false; + + /// The TypeKind identifies certain well-known types like size_t and + /// ptrdiff_t. + enum class TypeKind { DontCare, SizeT, PtrdiffT }; + TypeKind TK = TypeKind::DontCare; public: ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {} @@ -267,7 +272,9 @@ static ArgType Invalid() { return ArgType(InvalidTy); } bool isValid() const { return K != InvalidTy; } - bool isSizeT() const { return IsSizeT; } + bool isSizeT() const { return TK == TypeKind::SizeT; } + + bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; } /// Create an ArgType which corresponds to the type pointer to A. static ArgType PtrTo(const ArgType& A) { @@ -280,7 +287,15 @@ /// Create an ArgType which corresponds to the size_t/ssize_t type. static ArgType makeSizeT(const ArgType &A) { ArgType Res = A; -Res.IsSizeT = true; +Res.TK = TypeKind::SizeT; +return Res; + } + + /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t + /// type. + static ArgType makePtrdiffT(const ArgType &A) { +ArgType Res = A; +Res.TK = TypeKind::PtrdiffT; return Res; } Index: test/SemaObjC/format-size-spec-nsinteger.m === --- test/SemaObjC/format-size-spec-nsinteger.m +++ test/SemaObjC/format-size-spec-nsinteger.m @@ -1,16 +1,25 @@ // 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; @@ -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 +} Index: lib/Sema/SemaChecking.cpp === --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -6894,10 +6894,11 @@ QualType CastTy; std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E); if (!CastTy.isNull()) { - // %zi/%zu are OK to use for NSInteger/NSUInteger of type int + // %zi/%zu and %td/%tu are OK to use for NSInteger/NSUInteger of type int // (long in ASTContext). Only complain to pedants. if ((CastTyName == "NSInteger" || CastTyName == "NSUInteger") && - AT.isSizeT() && AT.matchesType(S.Context, CastTy)) + (AT.isSizeT() || AT.isPtrdiffT()) && + AT.matchesType(S.Context, CastTy)) Pedantic = true; IntendedTy = CastTy; ShouldNotPrintDirectly = true; Index: lib/Analysis/PrintfFormatString.cpp === --- lib/Analysis/PrintfFormatString.cpp +++ lib/Analysis/PrintfFormatString.cpp @@ -472,7 +472,8 @@ ? ArgType(Ctx.LongLongTy, "__int64") : ArgType(Ctx.IntTy, "__int32"); case LengthModifier::AsPtrDiff: -return ArgType(Ctx.getPointerDiffType()
[PATCH] D48852: [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin
aaron.ballman added a comment. In https://reviews.llvm.org/D48852#1153598, @arphaman wrote: > In https://reviews.llvm.org/D48852#1153415, @aaron.ballman wrote: > > > > This is acceptable because Darwin guarantees that, despite the watchOS > > > ABI differences, sizeof(ptrdiff_t) == sizeof(NS[U]Integer) > > > > Can you describe these ABI differences please? Also, does Darwin guarantee > > that alignof(ptrdiff_t) == alignof(NS[U]Integer)? > > > 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 iOS target (armv7k) uses 'ptrdiff_t' of type 'long', which > doesn't match 'NSInteger' of type 'int'. Thank you for the explanation, I appreciate it. https://reviews.llvm.org/D48852 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48852: [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin
arphaman updated this revision to Diff 154294. arphaman marked an inline comment as done. arphaman added a comment. Address review comments. https://reviews.llvm.org/D48852 Files: include/clang/Analysis/Analyses/FormatString.h lib/Analysis/PrintfFormatString.cpp lib/Sema/SemaChecking.cpp test/SemaObjC/format-size-spec-nsinteger.m Index: test/SemaObjC/format-size-spec-nsinteger.m === --- test/SemaObjC/format-size-spec-nsinteger.m +++ test/SemaObjC/format-size-spec-nsinteger.m @@ -1,16 +1,25 @@ // 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; @@ -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 +} Index: lib/Sema/SemaChecking.cpp === --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -6894,10 +6894,11 @@ QualType CastTy; std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E); if (!CastTy.isNull()) { - // %zi/%zu are OK to use for NSInteger/NSUInteger of type int + // %zi/%zu and %td/%tu are OK to use for NSInteger/NSUInteger of type int // (long in ASTContext). Only complain to pedants. if ((CastTyName == "NSInteger" || CastTyName == "NSUInteger") && - AT.isSizeT() && AT.matchesType(S.Context, CastTy)) + (AT.isSizeT() || AT.isPtrdiffT()) && + AT.matchesType(S.Context, CastTy)) Pedantic = true; IntendedTy = CastTy; ShouldNotPrintDirectly = true; Index: lib/Analysis/PrintfFormatString.cpp === --- lib/Analysis/PrintfFormatString.cpp +++ lib/Analysis/PrintfFormatString.cpp @@ -472,7 +472,8 @@ ? ArgType(Ctx.LongLongTy, "__int64") : ArgType(Ctx.IntTy, "__int32"); case LengthModifier::AsPtrDiff: -return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"); +return ArgType::makePtrdiffT( +ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: case LengthModifier::AsWide: @@ -505,7 +506,8 @@ ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); case LengthModifier::AsPtrDiff: -return ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"); +return ArgType::makePtrdiffT( +ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: case LengthModifier::AsWide: Index: include/clang/Analysis/Analyses/FormatString.h === --- include/clang/Analysis/Analyses/FormatString.h +++ include/clang/Analysis/Analyses/FormatString.h @@ -257,7 +257,12 @@ const Kind K; QualType T; const char *Name = nullptr; - bool Ptr = false, IsSizeT = false; + bool Ptr = false; + + /// The TypeKind identifies certain well-known types like size_t and + /// ptrdiff_t. + enum class TypeKind { DontCare, SizeT, PtrdiffT }; + TypeKind TK = TypeKind::DontCare; public: ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {} @@ -267,7 +272,9 @@ static ArgType Invalid() { return ArgType(InvalidTy); } bool isValid() const { return K != InvalidTy; } - bool isSizeT() const { return IsSizeT; } + bool isSizeT() const { return TK == TypeKin
[PATCH] D48852: [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin
arphaman marked an inline comment as done. arphaman added a comment. In https://reviews.llvm.org/D48852#1153415, @aaron.ballman wrote: > > This is acceptable because Darwin guarantees that, despite the watchOS ABI > > differences, sizeof(ptrdiff_t) == sizeof(NS[U]Integer) > > Can you describe these ABI differences please? Also, does Darwin guarantee > that alignof(ptrdiff_t) == alignof(NS[U]Integer)? 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 iOS target (armv7k) uses 'ptrdiff_t' of type 'long', which doesn't match 'NSInteger' of type 'int'. > Also, does Darwin guarantee that alignof(ptrdiff_t) == alignof(NS[U]Integer)? Yes. Comment at: include/clang/Analysis/Analyses/FormatString.h:265 + enum class TypeKind { Unspecified, SizeT, PtrdiffT }; + TypeKind TK = TypeKind::Unspecified; jfb wrote: > "unspecified" seems odd because it *is* specified, we just don't care. How > about something like "NothingSpecial" or "DontCare"? Thanks. Changed to "DontCare". Comment at: test/SemaObjC/format-size-spec-nsinteger.m:4 +// 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 jfb wrote: > We use a bunch of different triples to test WatchOS: > >5 thumbv7k-apple-watchos2.0 >3 i386-apple-watchos4 >2 x86_64-apple-watchos >2 thumbv7k-apple-watchos >2 armv7k-apple-watchos3.0.0 >2 armv7k-apple-watchos2.0 >2 armv7k-apple-watchos >1 x86_64-apple-watchos-simulator >1 thumbv7k-apple-watchos1.0 >1 i686-apple-watchos >1 i386-apple-watchos3.0-simulator >1 i386-apple-watchos3 >1 i386-apple-watchos2.1 >1 i386-apple-watchos2.0-simulator >1 i386-apple-watchos2.0 >1 i386-apple-watchos-simulator >1 i386-apple-watchos >1 armv7k-apple-watchos2.1 >1 armv7-apple-watchos >1 arm64-apple-watchos >1 aarch64-apple-watchos > > Do we care about v7k only for this test? Yes. armv7k is used to generate thumbv7k . i386 is used by simulator, and doesn't have this ABI issue. We don't support other arches for watches. Repository: rC Clang https://reviews.llvm.org/D48852 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48852: [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin
aaron.ballman added a comment. > This is acceptable because Darwin guarantees that, despite the watchOS ABI > differences, sizeof(ptrdiff_t) == sizeof(NS[U]Integer) Can you describe these ABI differences please? Also, does Darwin guarantee that alignof(ptrdiff_t) == alignof(NS[U]Integer)? Repository: rC Clang https://reviews.llvm.org/D48852 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48852: [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin
jfb accepted this revision. jfb added a comment. This revision is now accepted and ready to land. LGTM after a few questions. Comment at: include/clang/Analysis/Analyses/FormatString.h:265 + enum class TypeKind { Unspecified, SizeT, PtrdiffT }; + TypeKind TK = TypeKind::Unspecified; "unspecified" seems odd because it *is* specified, we just don't care. How about something like "NothingSpecial" or "DontCare"? Comment at: test/SemaObjC/format-size-spec-nsinteger.m:4 +// 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 We use a bunch of different triples to test WatchOS: 5 thumbv7k-apple-watchos2.0 3 i386-apple-watchos4 2 x86_64-apple-watchos 2 thumbv7k-apple-watchos 2 armv7k-apple-watchos3.0.0 2 armv7k-apple-watchos2.0 2 armv7k-apple-watchos 1 x86_64-apple-watchos-simulator 1 thumbv7k-apple-watchos1.0 1 i686-apple-watchos 1 i386-apple-watchos3.0-simulator 1 i386-apple-watchos3 1 i386-apple-watchos2.1 1 i386-apple-watchos2.0-simulator 1 i386-apple-watchos2.0 1 i386-apple-watchos-simulator 1 i386-apple-watchos 1 armv7k-apple-watchos2.1 1 armv7-apple-watchos 1 arm64-apple-watchos 1 aarch64-apple-watchos Do we care about v7k only for this test? Repository: rC Clang https://reviews.llvm.org/D48852 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48852: [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin
arphaman created this revision. arphaman added a reviewer: jfb. Herald added a subscriber: dexonsmith. The '%tu'/'%td' as formatting specifiers have been used to print out the NSInteger/NSUInteger values for a long time. Typically their ABI matches (i.e. ptrdiff_t = NSInteger), but that's not the case on watchOS (ptrdiff_t = long, NSInteger = int). 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), so the warning is therefore noisy for pedantic reasons. Once this is in I'll update public documentation. rdar://41739204 Repository: rC Clang https://reviews.llvm.org/D48852 Files: include/clang/Analysis/Analyses/FormatString.h lib/Analysis/PrintfFormatString.cpp lib/Sema/SemaChecking.cpp test/SemaObjC/format-size-spec-nsinteger.m Index: test/SemaObjC/format-size-spec-nsinteger.m === --- test/SemaObjC/format-size-spec-nsinteger.m +++ test/SemaObjC/format-size-spec-nsinteger.m @@ -1,16 +1,25 @@ // 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; @@ -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 +} Index: lib/Sema/SemaChecking.cpp === --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -6885,10 +6885,11 @@ QualType CastTy; std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E); if (!CastTy.isNull()) { - // %zi/%zu are OK to use for NSInteger/NSUInteger of type int + // %zi/%zu and %td/%tu are OK to use for NSInteger/NSUInteger of type int // (long in ASTContext). Only complain to pedants. if ((CastTyName == "NSInteger" || CastTyName == "NSUInteger") && - AT.isSizeT() && AT.matchesType(S.Context, CastTy)) + (AT.isSizeT() || AT.isPtrdiffT()) && + AT.matchesType(S.Context, CastTy)) Pedantic = true; IntendedTy = CastTy; ShouldNotPrintDirectly = true; Index: lib/Analysis/PrintfFormatString.cpp === --- lib/Analysis/PrintfFormatString.cpp +++ lib/Analysis/PrintfFormatString.cpp @@ -472,7 +472,8 @@ ? ArgType(Ctx.LongLongTy, "__int64") : ArgType(Ctx.IntTy, "__int32"); case LengthModifier::AsPtrDiff: -return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"); +return ArgType::makePtrdiffT( +ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: case LengthModifier::AsWide: @@ -505,7 +506,8 @@ ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); case LengthModifier::AsPtrDiff: -return ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"); +return ArgType::makePtrdiffT( +ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: case LengthModifier::AsWide: Index: include/clang/Analysis/Analyses/FormatStri