Skip to content

Commit 977a1e1

Browse files
committed
[Modules] Allow implicit conversions when loading interfaces with invalid os versions.
Initially, the compiler rejected building dependencies that contained OS versions in an invalid range. This happens to be quite disruptive, so instead allow it and request that these versions be implicitly bumped based on what `llvm::getCanonicalVersionForOS` computes
1 parent e42b564 commit 977a1e1

File tree

6 files changed

+126
-36
lines changed

6 files changed

+126
-36
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -895,10 +895,6 @@ ERROR(map_os_version_from_textual_interface_failed,none,
895895
"failed to map OS version from %0 to %1 in %2",
896896
(StringRef, StringRef, StringRef))
897897

898-
ERROR(target_os_version_from_textual_interface_invalid,none,
899-
"invalid target triple %0 in %1",
900-
(StringRef, StringRef))
901-
902898
ERROR(serialization_load_failed,Fatal,
903899
"failed to load module '%0'", (StringRef))
904900
ERROR(module_interface_build_failed,Fatal,

include/swift/Basic/Platform.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,16 @@ namespace swift {
123123
llvm::VersionTuple getTargetSDKVersion(clang::DarwinSDKInfo &SDKInfo,
124124
const llvm::Triple &triple);
125125

126+
/// Compute a target triple that is canonicalized using the passed triple.
127+
/// \returns nullopt if computation fails.
128+
std::optional<llvm::Triple> getCanonicalTriple(const llvm::Triple &triple);
129+
130+
/// Compare triples for equality but also including OSVersion.
131+
inline bool areTriplesStrictlyEqual(const llvm::Triple &lhs,
132+
const llvm::Triple &rhs) {
133+
return (lhs == rhs) && (lhs.getOSVersion() == rhs.getOSVersion());
134+
}
135+
126136
/// Get SDK build version.
127137
std::string getSDKBuildVersion(StringRef SDKPath);
128138
std::string getSDKBuildVersionFromPlist(StringRef Path);

lib/Basic/Platform.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,37 @@ llvm::VersionTuple swift::getTargetSDKVersion(clang::DarwinSDKInfo &SDKInfo,
848848
return SDKVersion;
849849
}
850850

851+
std::optional<llvm::Triple>
852+
swift::getCanonicalTriple(const llvm::Triple &triple) {
853+
llvm::Triple Result = triple;
854+
// Non-darwin targets do not require canonicalization.
855+
if (!triple.isOSDarwin())
856+
return Result;
857+
858+
// If the OS versions stay the same, return back the same triple.
859+
const llvm::VersionTuple inputOSVersion = triple.getOSVersion();
860+
const bool isOSVersionInValidRange =
861+
llvm::Triple::isValidVersionForOS(triple.getOS(), inputOSVersion);
862+
const llvm::VersionTuple canonicalVersion =
863+
llvm::Triple::getCanonicalVersionForOS(
864+
triple.getOS(), triple.getOSVersion(), isOSVersionInValidRange);
865+
if (canonicalVersion == triple.getOSVersion())
866+
return Result;
867+
868+
const std::string inputOSName = triple.getOSName().str();
869+
const std::string inputOSVersionAsStr = inputOSVersion.getAsString();
870+
const int platformNameLength =
871+
inputOSName.size() - inputOSVersionAsStr.size();
872+
if (!StringRef(inputOSName).ends_with(inputOSVersionAsStr) ||
873+
(platformNameLength <= 0))
874+
return std::nullopt;
875+
876+
llvm::SmallString<64> buffer(inputOSName.substr(0, platformNameLength));
877+
buffer.append(canonicalVersion.getAsString());
878+
Result.setOSName(buffer.str());
879+
return Result;
880+
}
881+
851882
static std::string getPlistEntry(const llvm::Twine &Path, StringRef KeyName) {
852883
auto BufOrErr = llvm::MemoryBuffer::getFile(Path);
853884
if (!BufOrErr) {

lib/ClangImporter/ClangImporter.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,11 @@ void importer::getNormalInvocationArguments(
478478
if (LangOpts.ClangTarget.has_value() && !ignoreClangTarget) {
479479
triple = LangOpts.ClangTarget.value();
480480
}
481+
auto canonicalTriple = getCanonicalTriple(triple);
482+
if (canonicalTriple.has_value() &&
483+
!areTriplesStrictlyEqual(*canonicalTriple, triple))
484+
triple = *canonicalTriple;
485+
481486
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts;
482487
ClangImporterOptions &importerOpts = ctx.ClangImporterOpts;
483488
auto languageVersion = ctx.LangOpts.EffectiveLanguageVersion;
@@ -808,6 +813,11 @@ importer::addCommonInvocationArguments(
808813
if (ctx.LangOpts.ClangTarget.has_value() && !ignoreClangTarget) {
809814
triple = ctx.LangOpts.ClangTarget.value();
810815
}
816+
auto canonicalTriple = getCanonicalTriple(triple);
817+
if (canonicalTriple.has_value() &&
818+
!areTriplesStrictlyEqual(*canonicalTriple, triple))
819+
triple = *canonicalTriple;
820+
811821
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts;
812822
const ClangImporterOptions &importerOpts = ctx.ClangImporterOpts;
813823

@@ -856,6 +866,12 @@ importer::addCommonInvocationArguments(
856866
invocationArgStrs.push_back("-darwin-target-variant");
857867
if (ctx.LangOpts.ClangTargetVariant.has_value() && !ignoreClangTarget)
858868
variantTriple = ctx.LangOpts.ClangTargetVariant.value();
869+
870+
auto canonicalVariantTriple = getCanonicalTriple(*variantTriple);
871+
if (canonicalVariantTriple.has_value() &&
872+
!areTriplesStrictlyEqual(*canonicalVariantTriple, *variantTriple))
873+
*variantTriple = *canonicalVariantTriple;
874+
859875
invocationArgStrs.push_back(variantTriple->str());
860876
}
861877

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,43 +1497,27 @@ bool swift::extractCompilerFlagsFromInterface(
14971497
shouldModify = true;
14981498
}
14991499

1500-
// Diagnose if the version in the target triple parsed from the
1501-
// swiftinterface is invalid for the OS.
1502-
const llvm::VersionTuple originalVer = triple.getOSVersion();
1503-
bool isValidVersion =
1504-
llvm::Triple::isValidVersionForOS(triple.getOS(), originalVer);
1505-
if (!isValidVersion) {
1500+
// Canonicalize the version in the target triple parsed from the
1501+
// swiftinterface.
1502+
auto canonicalTriple = getCanonicalTriple(triple);
1503+
if (!canonicalTriple.has_value()) {
15061504
if (Diag) {
1505+
const llvm::VersionTuple OSVersion = triple.getOSVersion();
1506+
const bool isOSVersionInValidRange =
1507+
llvm::Triple::isValidVersionForOS(triple.getOS(), OSVersion);
1508+
const llvm::VersionTuple canonicalVersion =
1509+
llvm::Triple::getCanonicalVersionForOS(
1510+
triple.getOS(), triple.getOSVersion(), isOSVersionInValidRange);
15071511
Diag->diagnose(SourceLoc(),
1508-
diag::target_os_version_from_textual_interface_invalid,
1509-
triple.str(), interfacePath);
1512+
diag::map_os_version_from_textual_interface_failed,
1513+
OSVersion.getAsString(), canonicalVersion.getAsString(),
1514+
interfacePath);
15101515
}
15111516
break;
15121517
}
1513-
1514-
// Canonicalize the version in the target triple parsed from the
1515-
// swiftinterface.
1516-
llvm::VersionTuple newVer = llvm::Triple::getCanonicalVersionForOS(
1517-
triple.getOS(), originalVer, isValidVersion);
1518-
if (originalVer != newVer) {
1519-
std::string originalOSName = triple.getOSName().str();
1520-
std::string originalVerStr = originalVer.getAsString();
1521-
std::string newVerStr = newVer.getAsString();
1522-
const int OSNameWithoutVersionLength =
1523-
originalOSName.size() - originalVerStr.size();
1524-
if (!StringRef(originalOSName).ends_with(originalVerStr) ||
1525-
(OSNameWithoutVersionLength <= 0)) {
1526-
if (Diag) {
1527-
Diag->diagnose(SourceLoc(),
1528-
diag::map_os_version_from_textual_interface_failed,
1529-
originalVerStr, newVerStr, interfacePath);
1530-
}
1531-
break;
1532-
}
1533-
llvm::SmallString<64> buffer(
1534-
originalOSName.substr(0, OSNameWithoutVersionLength));
1535-
buffer.append(newVerStr);
1536-
triple.setOSName(buffer.str());
1518+
// Update the triple to use if it differs.
1519+
if (!areTriplesStrictlyEqual(triple, *canonicalTriple)) {
1520+
triple = *canonicalTriple;
15371521
shouldModify = true;
15381522
}
15391523
if (shouldModify)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/module-cache)
3+
// RUN: split-file %s %t
4+
5+
// REQUIRES: OS=macosx || OS=maccatalyst
6+
7+
// First, test that the swift interface with an invalid os version behaves fine.
8+
// RUN: %target-swift-typecheck-module-from-interface(%t/Modules/Simple.swiftmodule/arm64-apple-macos.swiftinterface) -module-name Simple
9+
10+
// Next, build transitive dependencies in zippered mode.
11+
// RUN: %target-swift-frontend -module-name input %t/input.swift -target arm64-apple-macosx50.1 -target-variant arm64-apple-ios50.1-macabi -I%t/Modules -scan-dependencies -module-cache-path %t/module-cache-path -o %t/deps.json 2>&1 | Filecheck --allow-empty --implicit-check-not warning: --implicit-check-not error: %s
12+
// RUN: %validate-json %t/deps.json | %FileCheck %s --check-prefix=DEPS
13+
14+
DEPS-NOT: "arm64-apple-macos16.4"
15+
DEPS-NOT: "arm64-apple-ios22.0-macabi"
16+
DEPS: "arm64-apple-macos26.4"
17+
18+
//--- Modules/Simple.swiftmodule/arm64-apple-macos.swiftinterface
19+
// swift-interface-format-version: 1.0
20+
// swift-module-flags: -target arm64-apple-macos16.4
21+
public struct S {
22+
}
23+
24+
//--- Modules/Simple.swiftmodule/arm64-apple-ios-macabi.swiftinterface
25+
// swift-interface-format-version: 1.0
26+
// swift-module-flags: -target arm64-apple-ios22.0-macabi
27+
public struct S {
28+
}
29+
30+
//--- Modules/module.modulemap
31+
module ClangDep {
32+
header "ClangDep.h"
33+
export *
34+
}
35+
36+
//--- Modules/ClangDep.h
37+
typedef int my_int;
38+
39+
40+
//--- Modules/Interopt.swiftmodule/arm64-apple-macos.swiftinterface
41+
// swift-interface-format-version: 1.0
42+
// swift-module-flags: -target arm64-apple-macos16.4
43+
import Simple
44+
import ClangDep
45+
46+
//--- Modules/Interopt.swiftmodule/arm64-apple-ios-macabi.swiftinterface
47+
// swift-interface-format-version: 1.0
48+
// swift-module-flags: -target arm64-apple-ios22.0-macabi
49+
import Simple
50+
import ClangDep
51+
52+
//--- input.swift
53+
import Interopt

0 commit comments

Comments
 (0)