Teach ClangImporter to handle effective Swift version with minor release.

Needed to support Swift 4.2.
This commit is contained in:
Ted Kremenek
2018-03-23 00:30:44 -07:00
parent fa730db1c2
commit 3da51018b6
11 changed files with 195 additions and 19 deletions

View File

@@ -119,6 +119,9 @@ public:
/// Return this Version struct with minor and sub-minor components stripped
Version asMajorVersion() const;
/// Return this Version struct as the appropriate version string for APINotes.
std::string asAPINotesVersionString() const;
/// Parse a version in the form used by the _compiler_version \#if condition.
static Optional<Version> parseCompilerVersionString(StringRef VersionString,
SourceLoc Loc,

View File

@@ -17,6 +17,7 @@
#include "clang/Basic/CharInfo.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/Version.h"
@@ -302,8 +303,13 @@ Optional<Version> Version::getEffectiveLanguageVersion() const {
case 0:
return None;
case 1:
case 2:
break;
case 2:
// The only valid explicit language version with a minor
// component is 4.2.
if (Components[0] == 4 && Components[1] == 2)
break;
return None;
default:
// We do not want to permit users requesting more precise effective language
// versions since accepting such an argument promises more than we're able
@@ -327,9 +333,9 @@ Optional<Version> Version::getEffectiveLanguageVersion() const {
case 4:
static_assert(SWIFT_VERSION_MAJOR == 4,
"getCurrentLanguageVersion is no longer correct here");
// Version '4' on its own implies '4.1'.
// Version '4' on its own implies '4.1.50'.
if (size() == 1)
return Version{4, 1};
return Version{4, 1, 50};
return Version::getCurrentLanguageVersion();
case 5:
return Version{5, 0};
@@ -346,6 +352,16 @@ Version Version::asMajorVersion() const {
return res;
}
std::string Version::asAPINotesVersionString() const {
// Other than for "4.2.x", map the Swift major version into
// the API notes version for Swift. This has the effect of allowing
// API notes to effect changes only on Swift major versions,
// not minor versions.
if (size() >= 2 && Components[0] == 4 && Components[1] == 2)
return "4.2";
return llvm::itostr(Components[0]);
}
bool operator>=(const class Version &lhs,
const class Version &rhs) {

View File

@@ -611,12 +611,8 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
}
invocationArgStrs.push_back("-iapinotes-modules");
invocationArgStrs.push_back(searchPathOpts.RuntimeLibraryImportPath);
// Map the Swift major version into the API notes version for Swift. This
// has the effect of allowing API notes to effect changes only on Swift
// major versions, not minor versions.
invocationArgStrs.push_back("-fapinotes-swift-version=" +
llvm::itostr(languageVersion[0]));
languageVersion.asAPINotesVersionString());
}
static void

View File

@@ -578,6 +578,8 @@ checkVersionedSwiftName(VersionedSwiftNameInfo info,
if (!bestSoFar.empty() && bestSoFar <= info.Version)
return VersionedSwiftNameAction::Ignore;
auto requestedClangVersion = requestedVersion.asClangVersionTuple();
if (info.IsReplacedByActive) {
// We know that there are no versioned names between the active version and
// a replacement version, because otherwise /that/ name would be active.
@@ -586,7 +588,7 @@ checkVersionedSwiftName(VersionedSwiftNameInfo info,
// new value that is now active. (Special case: replacement = 0 means that
// a header annotation was replaced by an unversioned API notes annotation.)
if (info.Version.empty() ||
info.Version.getMajor() >= requestedVersion.majorVersionNumber()) {
info.Version >= requestedClangVersion) {
return VersionedSwiftNameAction::ResetToActive;
}
if (bestSoFar.empty())
@@ -594,7 +596,7 @@ checkVersionedSwiftName(VersionedSwiftNameInfo info,
return VersionedSwiftNameAction::Ignore;
}
if (info.Version.getMajor() < requestedVersion.majorVersionNumber())
if (info.Version < requestedClangVersion)
return VersionedSwiftNameAction::Ignore;
return VersionedSwiftNameAction::Use;
}

View File

@@ -56,12 +56,35 @@ class ImportNameVersion : public RelationalOperationsBase<ImportNameVersion> {
public:
/// Map a language version into an import name version.
static ImportNameVersion fromOptions(const LangOptions &langOpts) {
return ImportNameVersion(langOpts.EffectiveLanguageVersion[0]);
// We encode the 'rawValue' as just major version numbers with the
// exception of '4.2', which is a special minor version that can impact
// importing of names. We treat that with a rawValue of 5, and treat
// all major values of 5 or higher as being rawValue = majorversion + 1.
const auto &version = langOpts.EffectiveLanguageVersion;
if (version.size() > 1 && version[0] == 4 && version[1] == 2) {
return ImportNameVersion::swift4_2();
}
unsigned major = version[0];
return ImportNameVersion(major >= 5 ? major + 1 : major);
}
unsigned majorVersionNumber() const {
assert(*this != ImportNameVersion::raw());
return rawValue;
if (*this == ImportNameVersion::swift4_2())
return 4;
return rawValue < 5 ? rawValue : rawValue - 1;
}
unsigned minorVersionNumber() const {
assert(*this != ImportNameVersion::raw());
if (*this == ImportNameVersion::swift4_2())
return 2;
return 0;
}
clang::VersionTuple asClangVersionTuple() const {
assert(*this != ImportNameVersion::raw());
return clang::VersionTuple(majorVersionNumber(), minorVersionNumber());
}
bool operator==(ImportNameVersion other) const {
@@ -105,12 +128,17 @@ public:
return ImportNameVersion{2, AsConstExpr};
}
/// Names as they appeared in Swift 4.2 family.
static constexpr inline ImportNameVersion swift4_2() {
return ImportNameVersion{5, AsConstExpr};
}
/// The latest supported version.
///
/// FIXME: All other version information is in Version.h. Can this go there
/// instead?
static constexpr inline ImportNameVersion maxVersion() {
return ImportNameVersion{5, AsConstExpr};
return ImportNameVersion{6, AsConstExpr};
}
/// The version which should be used for importing types, which need to have

View File

@@ -259,7 +259,7 @@ SwiftVersions:
SwiftName: multiVersionedGlobal45Notes_5
- Name: multiVersionedGlobal45Both
SwiftName: multiVersionedGlobal45Both_5
- Version: 4 # Versions are deliberately ordered as "3, 5, 4" to catch bugs.
- Version: 4 # Versions are deliberately ordered as "3, 5, 4.2, 4" to catch bugs.
Globals:
- Name: multiVersionedGlobal34
SwiftName: multiVersionedGlobal34_4
@@ -293,3 +293,37 @@ SwiftVersions:
SwiftName: multiVersionedGlobal45Notes_4
- Name: multiVersionedGlobal45Both
SwiftName: multiVersionedGlobal45Both_4
- Version: 4.2
Globals:
- Name: multiVersionedGlobal34
SwiftName: multiVersionedGlobal34_4_2
- Name: multiVersionedGlobal34Header
SwiftName: multiVersionedGlobal34Header_4_2
- Name: multiVersionedGlobal34Notes
SwiftName: multiVersionedGlobal34Notes_4_2
- Name: multiVersionedGlobal34Both
SwiftName: multiVersionedGlobal34Both_4_2
- Name: multiVersionedGlobal345
SwiftName: multiVersionedGlobal345_4_2
- Name: multiVersionedGlobal345Header
SwiftName: multiVersionedGlobal345Header_4_2
- Name: multiVersionedGlobal345Notes
SwiftName: multiVersionedGlobal345Notes_4_2
- Name: multiVersionedGlobal345Both
SwiftName: multiVersionedGlobal345Both_4_2
- Name: multiVersionedGlobal4
SwiftName: multiVersionedGlobal4_4_2
- Name: multiVersionedGlobal4Header
SwiftName: multiVersionedGlobal4Header_4_2
- Name: multiVersionedGlobal4Notes
SwiftName: multiVersionedGlobal4Notes_4_2
- Name: multiVersionedGlobal4Both
SwiftName: multiVersionedGlobal4Both_4_2
- Name: multiVersionedGlobal45
SwiftName: multiVersionedGlobal45_4_2
- Name: multiVersionedGlobal45Header
SwiftName: multiVersionedGlobal45Header_4_2
- Name: multiVersionedGlobal45Notes
SwiftName: multiVersionedGlobal45Notes_4_2
- Name: multiVersionedGlobal45Both
SwiftName: multiVersionedGlobal45Both_4_2

View File

@@ -4,6 +4,8 @@
// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -swift-version 4 | %FileCheck -check-prefix=CHECK-SWIFT-4 %s
// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -swift-version 4.2 | %FileCheck -check-prefix=CHECK-SWIFT-4-2 %s
// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -swift-version 5 | %FileCheck -check-prefix=CHECK-SWIFT-5 %s
// CHECK-SWIFT-3: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4_4")
@@ -199,6 +201,101 @@
// CHECK-SWIFT-4: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345Both_4")
// CHECK-SWIFT-4: var multiVersionedGlobal345Both_5: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal4: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal4_4: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal4Notes: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal4Notes_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal4Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal4Notes_NEW: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal4Header: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal4Header_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal4Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal4Header_NEW: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal4Both: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal4Both_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal4Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal4Both_NEW: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal34_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34_3: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal34_4: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Notes: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal34Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Notes_3: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Notes_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal34Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Notes_NEW: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Header: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal34Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Header_3: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Header_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal34Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Header_NEW: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Both: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal34Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Both_3: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Both_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal34Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal34Both_NEW: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal45_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal45: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal45_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal45_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal45_5: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal45Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal45Notes: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal45Notes_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal45Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal45Notes_5: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal45Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal45Header: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal45Header_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal45Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal45Header_5: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal45Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal45Both: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal45Both_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal45Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal45Both_5: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal345_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal345_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345_3: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal345_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345_5: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal345Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Notes: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal345Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Notes_3: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Notes_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345Notes_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Notes_5: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal345Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Header: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal345Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Header_3: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Header_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345Header_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Header_5: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal345Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Both: Int32
// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal345Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Both_3: Int32
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Both_4: Int32
// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345Both_4_2")
// CHECK-SWIFT-4-2: var multiVersionedGlobal345Both_5: Int32
// CHECK-SWIFT-5: var multiVersionedGlobal4: Int32
// CHECK-SWIFT-5: @available(swift, obsoleted: 5, renamed: "multiVersionedGlobal4")

View File

@@ -14,7 +14,7 @@
// RUN: not %target-swiftc_driver -swift-version 5 -typecheck %s 2>&1 | %FileCheck --check-prefix ERROR_5 %s
// BAD: invalid value
// BAD: note: valid arguments to '-swift-version' are '3', '4', '5'
// BAD: note: valid arguments to '-swift-version' are '3', '4', '4.2', '5'
// FIXIT_3: use major version, as in '-swift-version 3'
// FIXIT_4: use major version, as in '-swift-version 4'

View File

@@ -1,4 +1,4 @@
// RUN: %target-typecheck-verify-swift -swift-version 4
// RUN: %target-typecheck-verify-swift -swift-version 4.2
#if swift(>=4)
let w = 1

View File

@@ -2,7 +2,7 @@
// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules -swift-version 3 %s
// RUN: echo 'import Lib; _ = Sub.disappearingMethod' | not --crash %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -swift-version 3 -disable-deserialization-recovery -Xcc -DBAD - 2>&1 | %FileCheck -check-prefix CHECK-CRASH -check-prefix CHECK-CRASH-3 %s
// RUN: echo 'import Lib; _ = Sub.disappearingMethod' | not --crash %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -swift-version 4 -disable-deserialization-recovery -Xcc -DBAD - 2>&1 | %FileCheck -check-prefix CHECK-CRASH -check-prefix CHECK-CRASH-4 %s
// RUN: echo 'import Lib; _ = Sub.disappearingMethod' | not --crash %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -swift-version 4.2 -disable-deserialization-recovery -Xcc -DBAD - 2>&1 | %FileCheck -check-prefix CHECK-CRASH -check-prefix CHECK-CRASH-4 %s
// REQUIRES: objc_interop

View File

@@ -16,8 +16,8 @@ import Lib
func requiresConformance(_: B_RequiresConformance<B_ConformsToProto>) {}
func requiresConformance(_: B_RequiresConformance<C_RelyOnConformanceImpl.Assoc>) {}
class Sub: Base {} // expected-error {{cannot inherit from class 'Base' (compiled with Swift 4.2) because it has overridable members that could not be loaded in Swift 3.4}}
class Impl: Proto {} // expected-error {{type 'Impl' cannot conform to protocol 'Proto' (compiled with Swift 4.2) because it has requirements that could not be loaded in Swift 3.4}}
class Sub: Base {} // expected-error {{cannot inherit from class 'Base' (compiled with Swift 4.1.50) because it has overridable members that could not be loaded in Swift 3.4}}
class Impl: Proto {} // expected-error {{type 'Impl' cannot conform to protocol 'Proto' (compiled with Swift 4.1.50) because it has requirements that could not be loaded in Swift 3.4}}
#else // TEST