Skip to content

Commit 0096904

Browse files
committed
Parse: Diagnose empty version numbers.
The compiler treats version tuples that are all zeros as empty, or the same as not having a version. Diagnose attempts to specify all-zeroes versions in attributes and availability queries to prevent surprising behavior. Resolves rdar://124661151
1 parent 9b41669 commit 0096904

6 files changed

+36
-1
lines changed

Diff for: lib/Parse/ParseDecl.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -4089,6 +4089,11 @@ bool Parser::parseVersionTuple(llvm::VersionTuple &Version,
40894089
Version = llvm::VersionTuple(major);
40904090
Range = SourceRange(StartLoc, Tok.getLoc());
40914091
consumeToken();
4092+
if (Version.empty()) {
4093+
// Versions cannot be empty (e.g. "0").
4094+
diagnose(Range.Start, D).warnUntilSwiftVersion(6);
4095+
return true;
4096+
}
40924097
return false;
40934098
}
40944099

@@ -4125,6 +4130,12 @@ bool Parser::parseVersionTuple(llvm::VersionTuple &Version,
41254130
Version = llvm::VersionTuple(major, minor);
41264131
}
41274132

4133+
if (Version.empty()) {
4134+
// Versions cannot be empty (e.g. "0.0").
4135+
diagnose(Range.Start, D).warnUntilSwiftVersion(6);
4136+
return true;
4137+
}
4138+
41284139
return false;
41294140
}
41304141

Diff for: test/Parse/availability_query.swift

+6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ if #available(OSX { // expected-error {{expected version number}} expected-error
3636
if #available(OSX) { // expected-error {{expected version number}}
3737
}
3838

39+
if #available(OSX 0) { // expected-warning {{expected version number; this is an error in the Swift 6 language mode}}
40+
}
41+
42+
if #available(OSX 0.0) { // expected-warning {{expected version number; this is an error in the Swift 6 language mode}}
43+
}
44+
3945
if #available(OSX 10.51 { // expected-error {{expected ')'}} expected-note {{to match this opening '('}} expected-error {{must handle potential future platforms with '*'}} {{24-24=, *}}
4046
}
4147

Diff for: test/Parse/invalid.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ let x: () = ()
139139
// https://github.com/apple/swift/issues/50734
140140

141141
func f1_50734(@NSApplicationMain x: Int) {} // expected-error {{@NSApplicationMain may only be used on 'class' declarations}}
142-
func f2_50734(@available(iOS, deprecated: 0) x: Int) {} // expected-error {{'@available' attribute cannot be applied to this declaration}}
142+
func f2_50734(@available(iOS, deprecated: 1) x: Int) {} // expected-error {{'@available' attribute cannot be applied to this declaration}}
143143
func f3_50734(@discardableResult x: Int) {} // expected-error {{'@discardableResult' attribute cannot be applied to this declaration}}
144144
func f4_50734(@objcMembers x: String) {} // expected-error {{@objcMembers may only be used on 'class' declarations}}
145145
func f5_50734(@weak x: String) {} // expected-error {{'weak' is a declaration modifier, not an attribute}} expected-error {{'weak' may only be used on 'var' declarations}}

Diff for: test/Sema/diag_originally_definedin.swift

+6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ public class C {
1616
@_originallyDefinedIn(module: "original", OSX 10.13)
1717
public class D {}
1818

19+
@_originallyDefinedIn(module: "original", macOS) // expected-error {{expected version number in '@_originallyDefinedIn' attribute}}
20+
public func missingVersion() {}
21+
22+
@_originallyDefinedIn(module: "original", macOS 0) // expected-warning {{expected version number in '@_originallyDefinedIn' attribute; this is an error in the Swift 6 language mode}}
23+
public func versionZero() {}
24+
1925
@available(macOS 10.9, *)
2026
@_originallyDefinedIn(module: "original", _myProject 2.0) // expected-error {{reference to undefined version '2.0' for availability macro '_myProject'}}
2127
public func macroVersioned() {}

Diff for: test/attr/attr_availability.swift

+9
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,15 @@ let _: Int
146146
@available(OSX, introduced: 1.0.0x4) // expected-error{{expected version number in 'available' attribute}}
147147
let _: Int
148148

149+
@available(OSX, introduced: 0) // expected-warning{{expected version number in 'available' attribute; this is an error in the Swift 6 language mode}}
150+
let _: Int
151+
152+
@available(OSX, introduced: 0.0) // expected-warning{{expected version number in 'available' attribute; this is an error in the Swift 6 language mode}}
153+
let _: Int
154+
155+
@available(OSX, introduced: 0.0.0) // expected-warning{{expected version number in 'available' attribute; this is an error in the Swift 6 language mode}}
156+
let _: Int
157+
149158
@available(*, renamed: "bad name") // expected-error{{'renamed' argument of 'available' attribute must be an operator, identifier, or full function name, optionally prefixed by a type name}}
150159
let _: Int
151160

Diff for: test/attr/attr_backDeployed.swift

+3
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ public func missingVersionFunc2() {}
384384
@backDeployed(before: macOS, iOS) // expected-error 2{{expected version number in '@backDeployed' attribute}}
385385
public func missingVersionFunc3() {}
386386

387+
@backDeployed(before: macOS 0) // expected-warning {{expected version number in '@backDeployed' attribute; this is an error in the Swift 6 language mode}}
388+
public func missingVersionFunc4() {}
389+
387390
@backDeployed(before: macOS 12.0, iOS 15.0,) // expected-error {{unexpected ',' separator}}
388391
public func unexpectedSeparatorFunc() {}
389392

0 commit comments

Comments
 (0)