From ae156fd3e49c0a4cba72dc90a31b463c3f763e17 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 17 May 2018 11:51:49 +0000 Subject: [PATCH] Use dotted format of version tuple for availability diagnostics E. g. use "10.11" instead of "10_11". We are maintaining backward compatibility by parsing underscore-delimited version tuples but no longer keep track of the separator and using dot format for output. Differential Revision: https://reviews.llvm.org/D46747 rdar://problem/39845032 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@332598 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/VersionTuple.h | 43 +++++++++----------------- lib/AST/DeclBase.cpp | 3 -- lib/Basic/VersionTuple.cpp | 6 ++-- lib/Parse/ParseDecl.cpp | 10 +++--- test/Misc/ast-print-objectivec.m | 2 +- test/Sema/availability-guard-format.mm | 15 +++++++++ test/SemaObjC/attr-availability-1.m | 4 +-- 7 files changed, 41 insertions(+), 42 deletions(-) create mode 100644 test/Sema/availability-guard-format.mm diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h index fad77f2d32..e7385b0b3b 100644 --- a/include/clang/Basic/VersionTuple.h +++ b/include/clang/Basic/VersionTuple.h @@ -24,9 +24,7 @@ namespace clang { /// Represents a version number in the form major[.minor[.subminor[.build]]]. class VersionTuple { - unsigned Major : 31; - - unsigned UsesUnderscores : 1; + unsigned Major : 32; unsigned Minor : 31; unsigned HasMinor : 1; @@ -39,30 +37,25 @@ class VersionTuple { public: VersionTuple() - : Major(0), UsesUnderscores(false), Minor(0), HasMinor(false), - Subminor(0), HasSubminor(false), Build(0), HasBuild(false) {} + : Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false), + Build(0), HasBuild(false) {} explicit VersionTuple(unsigned Major) - : Major(Major), UsesUnderscores(false), Minor(0), HasMinor(false), - Subminor(0), HasSubminor(false), Build(0), HasBuild(false) {} + : Major(Major), Minor(0), HasMinor(false), Subminor(0), + HasSubminor(false), Build(0), HasBuild(false) {} - explicit VersionTuple(unsigned Major, unsigned Minor, - bool UsesUnderscores = false) - : Major(Major), UsesUnderscores(UsesUnderscores), Minor(Minor), - HasMinor(true), Subminor(0), HasSubminor(false), Build(0), - HasBuild(false) {} + explicit VersionTuple(unsigned Major, unsigned Minor) + : Major(Major), Minor(Minor), HasMinor(true), Subminor(0), + HasSubminor(false), Build(0), HasBuild(false) {} - explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor, - bool UsesUnderscores = false) - : Major(Major), UsesUnderscores(UsesUnderscores), Minor(Minor), - HasMinor(true), Subminor(Subminor), HasSubminor(true), Build(0), - HasBuild(false) {} + explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor) + : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor), + HasSubminor(true), Build(0), HasBuild(false) {} explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor, - unsigned Build, bool UsesUnderscores = false) - : Major(Major), UsesUnderscores(UsesUnderscores), Minor(Minor), - HasMinor(true), Subminor(Subminor), HasSubminor(true), Build(Build), - HasBuild(true) {} + unsigned Build) + : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor), + HasSubminor(true), Build(Build), HasBuild(true) {} /// Determine whether this version information is empty /// (e.g., all version components are zero). @@ -93,14 +86,6 @@ public: return None; return Build; } - - bool usesUnderscores() const { - return UsesUnderscores; - } - - void UseDotAsSeparator() { - UsesUnderscores = false; - } /// Determine if two version numbers are equivalent. If not /// provided, minor and subminor version numbers are considered to be zero. diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 5c8915774f..51518a7862 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -550,7 +550,6 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, Message->clear(); llvm::raw_string_ostream Out(*Message); VersionTuple VTI(A->getIntroduced()); - VTI.UseDotAsSeparator(); Out << "introduced in " << PrettyPlatformName << ' ' << VTI << HintMessage; } @@ -564,7 +563,6 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, Message->clear(); llvm::raw_string_ostream Out(*Message); VersionTuple VTO(A->getObsoleted()); - VTO.UseDotAsSeparator(); Out << "obsoleted in " << PrettyPlatformName << ' ' << VTO << HintMessage; } @@ -578,7 +576,6 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, Message->clear(); llvm::raw_string_ostream Out(*Message); VersionTuple VTD(A->getDeprecated()); - VTD.UseDotAsSeparator(); Out << "first deprecated in " << PrettyPlatformName << ' ' << VTD << HintMessage; } diff --git a/lib/Basic/VersionTuple.cpp b/lib/Basic/VersionTuple.cpp index 9c73fd98a1..7a9176a808 100644 --- a/lib/Basic/VersionTuple.cpp +++ b/lib/Basic/VersionTuple.cpp @@ -29,11 +29,11 @@ raw_ostream& clang::operator<<(raw_ostream &Out, const VersionTuple &V) { Out << V.getMajor(); if (Optional Minor = V.getMinor()) - Out << (V.usesUnderscores() ? '_' : '.') << *Minor; + Out << '.' << *Minor; if (Optional Subminor = V.getSubminor()) - Out << (V.usesUnderscores() ? '_' : '.') << *Subminor; + Out << '.' << *Subminor; if (Optional Build = V.getBuild()) - Out << (V.usesUnderscores() ? '_' : '.') << *Build; + Out << '.' << *Build; return Out; } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 385d0fb3e7..456214f066 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -762,8 +762,10 @@ static bool VersionNumberSeparator(const char Separator) { /// /// version: /// simple-integer -/// simple-integer ',' simple-integer -/// simple-integer ',' simple-integer ',' simple-integer +/// simple-integer '.' simple-integer +/// simple-integer '_' simple-integer +/// simple-integer '.' simple-integer '.' simple-integer +/// simple-integer '_' simple-integer '_' simple-integer VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { Range = SourceRange(Tok.getLocation(), Tok.getEndLoc()); @@ -841,7 +843,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { return VersionTuple(); } - return VersionTuple(Major, Minor, (AfterMajorSeparator == '_')); + return VersionTuple(Major, Minor); } const char AfterMinorSeparator = ThisTokBegin[AfterMinor]; @@ -872,7 +874,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { return VersionTuple(); } ConsumeToken(); - return VersionTuple(Major, Minor, Subminor, (AfterMajorSeparator == '_')); + return VersionTuple(Major, Minor, Subminor); } /// Parse the contents of the "availability" attribute. diff --git a/test/Misc/ast-print-objectivec.m b/test/Misc/ast-print-objectivec.m index cb5aacc06a..eb1b469610 100644 --- a/test/Misc/ast-print-objectivec.m +++ b/test/Misc/ast-print-objectivec.m @@ -30,7 +30,7 @@ // CHECK: @end // CHECK: @interface I(CAT) -// CHECK: - (void)MethCAT __attribute__((availability(macos, introduced=10_1_0, deprecated=10_2))); +// CHECK: - (void)MethCAT __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))); // CHECK: @end // CHECK: @implementation I diff --git a/test/Sema/availability-guard-format.mm b/test/Sema/availability-guard-format.mm new file mode 100644 index 0000000000..910de49ffc --- /dev/null +++ b/test/Sema/availability-guard-format.mm @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx-10.11 -Wunguarded-availability -fdiagnostics-parseable-fixits -fsyntax-only -verify %s + +// Testing that even for source code using '_' as a delimiter in availability version tuple '.' is actually used in diagnostic output as a delimiter. + +@interface foo +- (void) method_bar __attribute__((availability(macosx, introduced = 10_12))); // expected-note {{'method_bar' has been explicitly marked partial here}} +@end + +int main() { + [foo method_bar]; // \ + // expected-warning {{'method_bar' is only available on macOS 10.12 or newer}} \ + // expected-note {{enclose 'method_bar' in an @available check to silence this warning}} \ + // CHECK: "fix-it:.*if (@available(macOS 10.12, *))" + return 0; +} diff --git a/test/SemaObjC/attr-availability-1.m b/test/SemaObjC/attr-availability-1.m index d3d4000378..cd7968fc72 100644 --- a/test/SemaObjC/attr-availability-1.m +++ b/test/SemaObjC/attr-availability-1.m @@ -25,10 +25,10 @@ // rdar://11475360 @interface B : A - (void)method; // NOTE: we expect 'method' to *not* inherit availability. -- (void)overridden __attribute__((availability(macosx,introduced=10_4))); // expected-warning{{overriding method introduced after overridden method on macOS (10_4 vs. 10_3)}} +- (void)overridden __attribute__((availability(macosx,introduced=10_4))); // expected-warning{{overriding method introduced after overridden method on macOS (10.4 vs. 10.3)}} - (void)overridden2 __attribute__((availability(macosx,introduced=10_2))); - (void)overridden3 __attribute__((availability(macosx,deprecated=10_4))); -- (void)overridden4 __attribute__((availability(macosx,deprecated=10_2))); // expected-warning{{overriding method deprecated before overridden method on macOS (10_3 vs. 10_2)}} +- (void)overridden4 __attribute__((availability(macosx,deprecated=10_2))); // expected-warning{{overriding method deprecated before overridden method on macOS (10.3 vs. 10.2)}} - (void)overridden5 __attribute__((availability(macosx,introduced=10_3))); - (void)overridden6 __attribute__((availability(macosx,unavailable))); // expected-warning{{overriding method cannot be unavailable on macOS when its overridden method is available}} @end -- 2.40.0