You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The `SWIFT_COMPILER_VERSION` define is used to stamp a vendor’s version number into a Swift compiler binary. It can be queried from Swift code using `#if _compiler_version` and from Clang by using a preprocessor definition called `__SWIFT_COMPILER_VERSION`. These are unsupported compiler-internal features used primarily by Apple Swift.
In Swift 1.0 through 5.5, Apple Swift used a scheme for `SWIFT_COMPILER_VERSION` where the major version matched the embedded clang (e.g. 1300 for Apple Clang 13.0.0) and the minor version was ignored. Starting in Swift 5.6, Apple Swift started using major and minor version numbers that matched the Swift.org version number. This makes them easier to understand, but it means that version 1300.0.x was followed by version 5.6.x. Not only did version numbers go backwards, but also the old logic to ignore minor versions was now a liability, because it meant you would not be able to target a change to 5.7.x compilers but not 5.6.x compilers.
This commit addresses the problem by:
* Modifying the existing `#if _compiler_version(string-literal)` feature so it transforms the major version into a major and minor that will compare correctly to new version numbers. For instance, “1300.*” is transformed into “1.300”, which will compare correctly to a “5.6” or “5.7” version even if it doesn’t really capture the fact that “1300” was a Swift 5.5 compiler. As a bonus, this allows you to use the feature to backwards-compatibly test new compilers using the existing feature: “5007.*” will be seen by compilers before 5.7 as an unknown future version, but will be seen by 5.7 compilers as targeting them.
* Modifying the `__SWIFT_COMPILER_VERSION` clang define similarly so that, to preprocessor conditions written for the old scheme, a 5.7 compiler will appear to have major version 5007.
* Adding a new variant of `#if _compiler_version` with the same syntax as `#if swift` and `#if compiler`—that is, taking a comparison operator and a bare set of dotted version numbers, rather than a string literal. Going forward, this will be how version checks are written once compatibility with compilers before this change is no longer a concern.
These changes are only lightly tested because tests have to work without any compiler version defined (the default in most configurations), but I’ve tested what I can.
Fixes rdar://89841295.
Copy file name to clipboardExpand all lines: test/Parse/ConditionalCompilation/compiler_version.swift
+16-2Lines changed: 16 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@
7
7
asdf asdf asdf asdf
8
8
#endif
9
9
10
-
#if _compiler_version("10.*.10.10")
10
+
#if _compiler_version("600.*.10.10")
11
11
12
12
#if os(iOS)
13
13
letz=1
@@ -48,7 +48,10 @@
48
48
letthisWillStillParseBecauseConfigIsError=1
49
49
#endif
50
50
51
-
#if _compiler_version("700.0.100") // expected-warning {{the second version component is not used for comparison}}
51
+
#if _compiler_version("700.0.100") // expected-warning {{the second version component is not used for comparison in legacy compiler versions}} {{28-29=*}}
52
+
#endif
53
+
54
+
#if _compiler_version("5.7.100") // expected-warning {{the second version component is not used for comparison in legacy compiler versions; are you trying to encode a new Swift compiler version for compatibility with legacy compilers?}} {{24-27=5007.*}}
52
55
#endif
53
56
54
57
#if _compiler_version("700.*.1.1.1.1") // expected-error {{version must not have more than five components}}
@@ -65,3 +68,14 @@
65
68
66
69
#if _compiler_version("700.*.1.1.1000") // expected-error {{version component out of range: must be in [0, 999]}}
0 commit comments