Skip to content

Commit 9172d66

Browse files
authored
Merge pull request #61014 from CodaFi/version-militude
2 parents 503e0e4 + a71b970 commit 9172d66

File tree

18 files changed

+350
-307
lines changed

18 files changed

+350
-307
lines changed

include/swift/Basic/Version.h

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
namespace swift {
3232

33-
class DiagnosticEngine;
33+
class VersionParser;
3434
class SourceLoc;
3535

3636
namespace version {
@@ -53,6 +53,7 @@ namespace version {
5353
/// a: [0 - 999]
5454
/// b: [0 - 999]
5555
class Version {
56+
friend class swift::VersionParser;
5657
SmallVector<unsigned, 5> Components;
5758
public:
5859
/// Create the empty compiler version - this always compares greater
@@ -63,11 +64,6 @@ class Version {
6364
/// Create a literal version from a list of components.
6465
Version(std::initializer_list<unsigned> Values) : Components(Values) {}
6566

66-
/// Create a version from a string in source code.
67-
///
68-
/// Must include only groups of digits separated by a dot.
69-
Version(StringRef VersionString, SourceLoc Loc, DiagnosticEngine *Diags);
70-
7167
/// Return a string to be used as an internal preprocessor define.
7268
///
7369
/// The components of the version are multiplied element-wise by
@@ -129,29 +125,6 @@ class Version {
129125
/// Return this Version struct as the appropriate version string for APINotes.
130126
std::string asAPINotesVersionString() const;
131127

132-
/// Parse a version in the form used by the _compiler_version(string-literal)
133-
/// \#if condition.
134-
///
135-
/// \note This is \em only used for the string literal version, so it includes
136-
/// backwards-compatibility logic to convert it to something that can be
137-
/// compared with a modern SWIFT_COMPILER_VERSION.
138-
static Optional<Version> parseCompilerVersionString(StringRef VersionString,
139-
SourceLoc Loc,
140-
DiagnosticEngine *Diags);
141-
142-
/// Parse a generic version string of the format [0-9]+(.[0-9]+)*
143-
///
144-
/// Version components can be any unsigned 64-bit number.
145-
static Optional<Version> parseVersionString(StringRef VersionString,
146-
SourceLoc Loc,
147-
DiagnosticEngine *Diags);
148-
149-
/// Returns a version from the currently defined SWIFT_COMPILER_VERSION.
150-
///
151-
/// If SWIFT_COMPILER_VERSION is undefined, this will return the empty
152-
/// compiler version.
153-
static Version getCurrentCompilerVersion();
154-
155128
/// Returns a version from the currently defined SWIFT_VERSION_MAJOR and
156129
/// SWIFT_VERSION_MINOR.
157130
static Version getCurrentLanguageVersion();
@@ -190,7 +163,7 @@ std::string getSwiftFullVersion(Version effectiveLanguageVersion =
190163
StringRef getSwiftRevision();
191164

192165
/// Is the running compiler built with a version tag for distribution?
193-
/// When true, \c Version::getCurrentCompilerVersion returns a valid version
166+
/// When true, \c version::getCurrentCompilerVersion returns a valid version
194167
/// and \c getCurrentCompilerTag returns the version tuple in string format.
195168
bool isCurrentCompilerTagged();
196169

include/swift/Parse/ParseVersion.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//===--- ParseVersion.h - Parser Swift Version Numbers ----------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_PARSE_PARSEVERSION_H
14+
#define SWIFT_PARSE_PARSEVERSION_H
15+
16+
#include "swift/Basic/Version.h"
17+
18+
namespace swift {
19+
class DiagnosticEngine;
20+
21+
namespace version {
22+
/// Returns a version from the currently defined SWIFT_COMPILER_VERSION.
23+
///
24+
/// If SWIFT_COMPILER_VERSION is undefined, this will return the empty
25+
/// compiler version.
26+
Version getCurrentCompilerVersion();
27+
} // namespace version
28+
29+
class VersionParser final {
30+
public:
31+
/// Parse a version in the form used by the _compiler_version(string-literal)
32+
/// \#if condition.
33+
///
34+
/// \note This is \em only used for the string literal version, so it includes
35+
/// backwards-compatibility logic to convert it to something that can be
36+
/// compared with a modern SWIFT_COMPILER_VERSION.
37+
static Optional<version::Version>
38+
parseCompilerVersionString(StringRef VersionString, SourceLoc Loc,
39+
DiagnosticEngine *Diags);
40+
41+
/// Parse a generic version string of the format [0-9]+(.[0-9]+)*
42+
///
43+
/// Version components can be any unsigned 64-bit number.
44+
static Optional<version::Version> parseVersionString(StringRef VersionString,
45+
SourceLoc Loc,
46+
DiagnosticEngine *Diags);
47+
};
48+
} // namespace swift
49+
50+
#endif // SWIFT_PARSE_PARSEVERSION_H

lib/Basic/CMakeLists.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,6 @@ target_link_libraries(swiftBasic PUBLIC
9898
target_link_libraries(swiftBasic PRIVATE
9999
${UUID_LIBRARIES})
100100

101-
# This is because swiftBasic uses InFlightDiagnostic::flush, which is defined
102-
# in swiftAST. This is a cyclic link dependency and it should be removed.
103-
target_link_libraries(swiftBasic PUBLIC swiftAST)
104-
105101
message(STATUS "Swift version: ${SWIFT_VERSION}")
106102
message(STATUS "Swift vendor: ${SWIFT_VENDOR}")
107103

lib/Basic/Version.cpp

Lines changed: 0 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616

1717
#include "clang/Basic/CharInfo.h"
1818
#include "llvm/Support/raw_ostream.h"
19-
#include "llvm/Support/FormatVariadic.h"
2019
#include "llvm/ADT/SmallString.h"
2120
#include "llvm/ADT/StringExtras.h"
22-
#include "swift/AST/DiagnosticsParse.h"
2321
#include "swift/Basic/LLVM.h"
2422
#include "swift/Basic/Version.h"
2523

@@ -68,222 +66,6 @@ static void printFullRevisionString(raw_ostream &out) {
6866
#endif
6967
}
7068

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-
28769
Version Version::getCurrentLanguageVersion() {
28870
#if SWIFT_VERSION_PATCHLEVEL
28971
return {SWIFT_VERSION_MAJOR, SWIFT_VERSION_MINOR, SWIFT_VERSION_PATCHLEVEL};

lib/ClangImporter/ClangImporter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "swift/ClangImporter/ClangImporterRequests.h"
4242
#include "swift/ClangImporter/ClangModule.h"
4343
#include "swift/Parse/Lexer.h"
44+
#include "swift/Parse/ParseVersion.h"
4445
#include "swift/Parse/Parser.h"
4546
#include "swift/Strings.h"
4647
#include "swift/Subsystems.h"
@@ -73,8 +74,8 @@
7374
#include "llvm/Support/VirtualFileSystem.h"
7475
#include "llvm/Support/YAMLParser.h"
7576
#include <algorithm>
76-
#include <string>
7777
#include <memory>
78+
#include <string>
7879

7980
using namespace swift;
8081
using namespace importer;
@@ -608,7 +609,7 @@ importer::getNormalInvocationArguments(
608609

609610
// Get the version of this compiler and pass it to C/Objective-C
610611
// declarations.
611-
auto V = version::Version::getCurrentCompilerVersion();
612+
auto V = version::getCurrentCompilerVersion();
612613
if (!V.empty()) {
613614
// Note: Prior to Swift 5.7, the "Y" version component was omitted and the
614615
// "X" component resided in its digits.

0 commit comments

Comments
 (0)