Skip to content

Commit 8efc741

Browse files
[Module] Use stricter module hash
Use a stricter module hash for modules as moving towards more explicit modules. Previously, a normalized target triple without deployment target is used as part of the module hash, with the assumption that deployment target should not change binary module generated. In reality, the binary module compilation also needs to provide the typecheck for all interface to ensure the underlying C/ObjC module that built with the correct deployment target does provide the interfaces to pass typecheck. Using a stricter module hash can avoid the potentially confusing error when importing the module. This commit adds following to module hash to distinguish swiftmodules. * Deployment target * -application-extension rdar://134301179
1 parent ec09fa7 commit 8efc741

File tree

3 files changed

+72
-10
lines changed

3 files changed

+72
-10
lines changed

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,8 +2071,24 @@ StringRef InterfaceSubContextDelegateImpl::computeCachedOutputPath(
20712071
std::string
20722072
InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath,
20732073
StringRef sdkPath) {
2074-
auto normalizedTargetTriple =
2075-
getTargetSpecificModuleTriple(genericSubInvocation.getLangOptions().Target);
2074+
// When doing dependency scanning for explicit module, use strict context hash
2075+
// to ensure sound module hash.
2076+
bool useStrictCacheHash =
2077+
genericSubInvocation.getFrontendOptions().RequestedAction ==
2078+
FrontendOptions::ActionType::ScanDependencies;
2079+
2080+
// Include the normalized target triple when not using strict hash.
2081+
// Otherwise, use the full target to ensure soundness of the hash. In
2082+
// practice, .swiftinterface files will be in target-specific subdirectories
2083+
// and would have target-specific pieces #if'd out. However, it doesn't hurt
2084+
// to include it, and it guards against mistakenly reusing cached modules
2085+
// across targets. Note that this normalization explicitly doesn't include the
2086+
// minimum deployment target (e.g. the '12.0' in 'ios12.0').
2087+
auto targetToHash = useStrictCacheHash
2088+
? genericSubInvocation.getLangOptions().Target
2089+
: getTargetSpecificModuleTriple(
2090+
genericSubInvocation.getLangOptions().Target);
2091+
20762092
std::string sdkBuildVersion = getSDKBuildVersion(sdkPath);
20772093
const auto ExtraArgs = genericSubInvocation.getClangImporterOptions()
20782094
.getReducedExtraArgsForSwiftModuleDependency();
@@ -2089,13 +2105,8 @@ InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath,
20892105
// anyways.
20902106
useInterfacePath,
20912107

2092-
// Include the normalized target triple. In practice, .swiftinterface
2093-
// files will be in target-specific subdirectories and would have
2094-
// target-specific pieces #if'd out. However, it doesn't hurt to include
2095-
// it, and it guards against mistakenly reusing cached modules across
2096-
// targets. Note that this normalization explicitly doesn't include the
2097-
// minimum deployment target (e.g. the '12.0' in 'ios12.0').
2098-
normalizedTargetTriple.str(),
2108+
// The target triple to hash.
2109+
targetToHash.str(),
20992110

21002111
// The SDK path is going to affect how this module is imported, so
21012112
// include it.
@@ -2121,6 +2132,10 @@ InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath,
21212132
// module.
21222133
llvm::hash_combine_range(ExtraArgs.begin(), ExtraArgs.end()),
21232134

2135+
/// Application extension.
2136+
unsigned(
2137+
genericSubInvocation.getLangOptions().EnableAppExtensionRestrictions),
2138+
21242139
// Whether or not OSSA modules are enabled.
21252140
//
21262141
// If OSSA modules are enabled, we use a separate namespace of modules to

test/ScanDependencies/module_hash.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -O \
1515
// RUN: -o %t/deps-3.json -Xcc -fapplication-extension -I %t/include
1616

17-
/// Check module hash for the swiftmodule. 1 and 2 should match, but not 3.
17+
/// Check module hash for the swiftmodule. They should all not match.
1818
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps-1.json Library modulePath > %t/path-1
1919
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps-2.json Library modulePath > %t/path-2
2020
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps-3.json Library modulePath > %t/path-3
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// REQUIRES: OS=macosx, objc_interop
2+
// RUN: %empty-directory(%t)
3+
// RUN: split-file %s %t
4+
5+
/// Different version should not match.
6+
// RUN: %target-swift-frontend -target %module-target-triple -scan-dependencies -module-name Test %t/main.swift -module-cache-path %t/clang-module-cache \
7+
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -O \
8+
// RUN: -o %t/deps-now.json -I %t/include
9+
// RUN: %target-swift-frontend -target %module-target-future -scan-dependencies -module-name Test %t/main.swift -module-cache-path %t/clang-module-cache \
10+
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -O \
11+
// RUN: -o %t/deps-future.json -I %t/include
12+
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps-now.json Library modulePath > %t/path-now
13+
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps-future.json Library modulePath > %t/path-future
14+
// RUN: not diff %t/path-now %t/path-future
15+
16+
/// Application extension should not match.
17+
// RUN: %target-swift-frontend -scan-dependencies -module-name Test %t/main.swift -module-cache-path %t/clang-module-cache \
18+
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -O \
19+
// RUN: -o %t/deps.json -I %t/include
20+
// RUN: %target-swift-frontend -scan-dependencies -module-name Test %t/main.swift -module-cache-path %t/clang-module-cache \
21+
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -O \
22+
// RUN: -o %t/deps-ae.json -I %t/include -application-extension
23+
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps.json Library modulePath > %t/path
24+
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps-ae.json Library modulePath > %t/path-ae
25+
// RUN: not diff %t/path %t/path-ae
26+
27+
//--- main.swift
28+
import Library
29+
30+
//--- include/Library.swiftinterface
31+
// swift-interface-format-version: 1.0
32+
// swift-module-flags: -module-name Library -O -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -user-module-version 1.0
33+
import Swift
34+
@_exported import A
35+
@inlinable
36+
public func test() {
37+
foo()
38+
}
39+
40+
//--- include/a.h
41+
void foo(void);
42+
43+
//--- include/module.modulemap
44+
module A {
45+
header "a.h"
46+
export *
47+
}

0 commit comments

Comments
 (0)