|
16 | 16 |
|
17 | 17 | #include "clang/Basic/CharInfo.h" |
18 | 18 | #include "llvm/Support/raw_ostream.h" |
19 | | -#include "llvm/Support/FormatVariadic.h" |
20 | 19 | #include "llvm/ADT/SmallString.h" |
21 | 20 | #include "llvm/ADT/StringExtras.h" |
22 | | -#include "swift/AST/DiagnosticsParse.h" |
23 | 21 | #include "swift/Basic/LLVM.h" |
24 | 22 | #include "swift/Basic/Version.h" |
25 | 23 |
|
@@ -68,222 +66,6 @@ static void printFullRevisionString(raw_ostream &out) { |
68 | 66 | #endif |
69 | 67 | } |
70 | 68 |
|
71 | | -static void splitVersionComponents( |
72 | | - SmallVectorImpl<std::pair<StringRef, SourceRange>> &SplitComponents, |
73 | | - StringRef &VersionString, SourceLoc Loc, |
74 | | - bool skipQuote = false) { |
75 | | - SourceLoc Start = (Loc.isValid() && skipQuote) ? Loc.getAdvancedLoc(1) : Loc; |
76 | | - SourceLoc End = Start; |
77 | | - |
78 | | - // Split the version string into tokens separated by the '.' character. |
79 | | - while (!VersionString.empty()) { |
80 | | - StringRef SplitComponent, Rest; |
81 | | - std::tie(SplitComponent, Rest) = VersionString.split('.'); |
82 | | - |
83 | | - if (Loc.isValid()) { |
84 | | - End = End.getAdvancedLoc(SplitComponent.size()); |
85 | | - } |
86 | | - auto Range = Loc.isValid() ? SourceRange(Start, End) : SourceRange(); |
87 | | - if (Loc.isValid()) |
88 | | - End = End.getAdvancedLoc(1); |
89 | | - Start = End; |
90 | | - SplitComponents.push_back({SplitComponent, Range}); |
91 | | - VersionString = Rest; |
92 | | - } |
93 | | -} |
94 | | - |
95 | | -Optional<Version> Version::parseCompilerVersionString( |
96 | | - StringRef VersionString, SourceLoc Loc, DiagnosticEngine *Diags) { |
97 | | - |
98 | | - Version CV; |
99 | | - SmallString<16> digits; |
100 | | - llvm::raw_svector_ostream OS(digits); |
101 | | - SmallVector<std::pair<StringRef, SourceRange>, 5> SplitComponents; |
102 | | - |
103 | | - splitVersionComponents(SplitComponents, VersionString, Loc, |
104 | | - /*skipQuote=*/true); |
105 | | - |
106 | | - uint64_t ComponentNumber; |
107 | | - bool isValidVersion = true; |
108 | | - |
109 | | - auto checkVersionComponent = [&](unsigned Component, SourceRange Range) { |
110 | | - unsigned limit = CV.Components.empty() ? 9223371 : 999; |
111 | | - |
112 | | - if (Component > limit) { |
113 | | - if (Diags) |
114 | | - Diags->diagnose(Range.Start, |
115 | | - diag::compiler_version_component_out_of_range, limit); |
116 | | - isValidVersion = false; |
117 | | - } |
118 | | - }; |
119 | | - |
120 | | - for (size_t i = 0; i < SplitComponents.size(); ++i) { |
121 | | - StringRef SplitComponent; |
122 | | - SourceRange Range; |
123 | | - std::tie(SplitComponent, Range) = SplitComponents[i]; |
124 | | - |
125 | | - // Version components can't be empty. |
126 | | - if (SplitComponent.empty()) { |
127 | | - if (Diags) |
128 | | - Diags->diagnose(Range.Start, diag::empty_version_component); |
129 | | - isValidVersion = false; |
130 | | - continue; |
131 | | - } |
132 | | - |
133 | | - // The second version component isn't used for comparison. |
134 | | - if (i == 1) { |
135 | | - if (!SplitComponent.equals("*")) { |
136 | | - if (Diags) { |
137 | | - // Majors 600-1300 were used for Swift 1.0-5.5 (based on clang |
138 | | - // versions), but then we reset the numbering based on Swift versions, |
139 | | - // so 5.6 had major 5. We assume that majors below 600 use the new |
140 | | - // scheme and equal/above it use the old scheme. |
141 | | - bool firstComponentLooksNew = CV.Components[0] < 600; |
142 | | - |
143 | | - auto diag = Diags->diagnose(Range.Start, |
144 | | - diag::unused_compiler_version_component, |
145 | | - firstComponentLooksNew); |
146 | | - |
147 | | - if (firstComponentLooksNew && |
148 | | - !SplitComponent.getAsInteger(10, ComponentNumber)) { |
149 | | - // Fix-it version like "5.7.1.2.3" to "5007.*.1.2.3". |
150 | | - auto newDigits = llvm::formatv("{0}{1,0+3}.*", CV.Components[0], |
151 | | - ComponentNumber).str(); |
152 | | - diag.fixItReplaceChars(SplitComponents[0].second.Start, |
153 | | - Range.End, newDigits); |
154 | | - } |
155 | | - else { |
156 | | - diag.fixItReplaceChars(Range.Start, Range.End, "*"); |
157 | | - } |
158 | | - } |
159 | | - } |
160 | | - |
161 | | - CV.Components.push_back(0); |
162 | | - continue; |
163 | | - } |
164 | | - |
165 | | - // All other version components must be numbers. |
166 | | - if (!SplitComponent.getAsInteger(10, ComponentNumber)) { |
167 | | - checkVersionComponent(ComponentNumber, Range); |
168 | | - CV.Components.push_back(ComponentNumber); |
169 | | - continue; |
170 | | - } else { |
171 | | - if (Diags) |
172 | | - Diags->diagnose(Range.Start, diag::version_component_not_number); |
173 | | - isValidVersion = false; |
174 | | - } |
175 | | - } |
176 | | - |
177 | | - if (CV.Components.size() > 5) { |
178 | | - if (Diags) |
179 | | - Diags->diagnose(Loc, diag::compiler_version_too_many_components); |
180 | | - isValidVersion = false; |
181 | | - } |
182 | | - |
183 | | - // In the beginning, '_compiler_version(string-literal)' was designed for a |
184 | | - // different version scheme where the major was fairly large and the minor |
185 | | - // was ignored; now we use one where the minor is significant and major and |
186 | | - // minor match the Swift language version. See the comment above on |
187 | | - // `firstComponentLooksNew` for details. |
188 | | - // |
189 | | - // However, we want the string literal variant of '_compiler_version' to |
190 | | - // maintain source compatibility with old checks; that means checks for new |
191 | | - // versions have to be written so that old compilers will think they represent |
192 | | - // newer versions, while new compilers have to interpret old version number |
193 | | - // strings in a way that will compare correctly to the new versions compiled |
194 | | - // into them. |
195 | | - // |
196 | | - // To achieve this, modern compilers divide the major by 1000 and overwrite |
197 | | - // the wildcard component with the remainder, effectively shifting the last |
198 | | - // three digits of the major into the minor, before comparing it to the |
199 | | - // compiler version: |
200 | | - // |
201 | | - // _compiler_version("5007.*.1.2.3") -> 5.7.1.2.3 |
202 | | - // _compiler_version("1300.*.1.2.3") -> 1.300.1.2.3 (smaller than 5.6) |
203 | | - // _compiler_version( "600.*.1.2.3") -> 0.600.1.2.3 (smaller than 5.6) |
204 | | - // |
205 | | - // So if you want to specify a 5.7.z.a.b version, we ask users to either write |
206 | | - // it as 5007.*.z.a.b, or to use the new '_compiler_version(>= version)' |
207 | | - // syntax instead, which does not perform this conversion. |
208 | | - if (!CV.Components.empty()) { |
209 | | - if (CV.Components.size() == 1) |
210 | | - CV.Components.push_back(0); |
211 | | - CV.Components[1] = CV.Components[0] % 1000; |
212 | | - CV.Components[0] = CV.Components[0] / 1000; |
213 | | - } |
214 | | - |
215 | | - return isValidVersion ? Optional<Version>(CV) : None; |
216 | | -} |
217 | | - |
218 | | -Optional<Version> Version::parseVersionString(StringRef VersionString, |
219 | | - SourceLoc Loc, |
220 | | - DiagnosticEngine *Diags) { |
221 | | - Version TheVersion; |
222 | | - SmallString<16> digits; |
223 | | - llvm::raw_svector_ostream OS(digits); |
224 | | - SmallVector<std::pair<StringRef, SourceRange>, 5> SplitComponents; |
225 | | - // Skip over quote character in string literal. |
226 | | - |
227 | | - if (VersionString.empty()) { |
228 | | - if (Diags) |
229 | | - Diags->diagnose(Loc, diag::empty_version_string); |
230 | | - return None; |
231 | | - } |
232 | | - |
233 | | - splitVersionComponents(SplitComponents, VersionString, Loc, Diags); |
234 | | - |
235 | | - uint64_t ComponentNumber; |
236 | | - bool isValidVersion = true; |
237 | | - |
238 | | - for (size_t i = 0; i < SplitComponents.size(); ++i) { |
239 | | - StringRef SplitComponent; |
240 | | - SourceRange Range; |
241 | | - std::tie(SplitComponent, Range) = SplitComponents[i]; |
242 | | - |
243 | | - // Version components can't be empty. |
244 | | - if (SplitComponent.empty()) { |
245 | | - if (Diags) |
246 | | - Diags->diagnose(Range.Start, diag::empty_version_component); |
247 | | - |
248 | | - isValidVersion = false; |
249 | | - continue; |
250 | | - } |
251 | | - |
252 | | - // All other version components must be numbers. |
253 | | - if (!SplitComponent.getAsInteger(10, ComponentNumber)) { |
254 | | - TheVersion.Components.push_back(ComponentNumber); |
255 | | - continue; |
256 | | - } else { |
257 | | - if (Diags) |
258 | | - Diags->diagnose(Range.Start, |
259 | | - diag::version_component_not_number); |
260 | | - isValidVersion = false; |
261 | | - } |
262 | | - } |
263 | | - |
264 | | - return isValidVersion ? Optional<Version>(TheVersion) : None; |
265 | | -} |
266 | | - |
267 | | -Version::Version(StringRef VersionString, |
268 | | - SourceLoc Loc, |
269 | | - DiagnosticEngine *Diags) |
270 | | - : Version(*parseVersionString(VersionString, Loc, Diags)) |
271 | | -{} |
272 | | - |
273 | | -Version Version::getCurrentCompilerVersion() { |
274 | | -#ifdef SWIFT_COMPILER_VERSION |
275 | | - auto currentVersion = Version::parseVersionString( |
276 | | - SWIFT_COMPILER_VERSION, SourceLoc(), nullptr); |
277 | | - assert(currentVersion.hasValue() && |
278 | | - "Embedded Swift language version couldn't be parsed: '" |
279 | | - SWIFT_COMPILER_VERSION |
280 | | - "'"); |
281 | | - return currentVersion.getValue(); |
282 | | -#else |
283 | | - return Version(); |
284 | | -#endif |
285 | | -} |
286 | | - |
287 | 69 | Version Version::getCurrentLanguageVersion() { |
288 | 70 | #if SWIFT_VERSION_PATCHLEVEL |
289 | 71 | return {SWIFT_VERSION_MAJOR, SWIFT_VERSION_MINOR, SWIFT_VERSION_PATCHLEVEL}; |
|
0 commit comments