Skip to content

Commit 8734d2e

Browse files
committed
[Dependency Scanning] Detect cycles of main target module depending on an existing Swift textual or prebuilt binary module
Resolves rdar://123112402
1 parent 9607e9d commit 8734d2e

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,9 @@ static bool diagnoseCycle(CompilerInstance &instance,
12991299
[&buffer](const ModuleDependencyID &id) {
13001300
buffer.append(id.ModuleName);
13011301
switch (id.Kind) {
1302+
case swift::ModuleDependencyKind::SwiftSource:
1303+
buffer.append(" (Source Target)");
1304+
break;
13021305
case swift::ModuleDependencyKind::SwiftInterface:
13031306
buffer.append(".swiftinterface");
13041307
break;
@@ -1318,11 +1321,12 @@ static bool diagnoseCycle(CompilerInstance &instance,
13181321
[&buffer] { buffer.append(" -> "); });
13191322
};
13201323

1321-
auto emitCycleDiagnostic = [&](const ModuleDependencyID &dep) {
1322-
auto startIt = std::find(openSet.begin(), openSet.end(), dep);
1324+
auto emitCycleDiagnostic = [&](const ModuleDependencyID &sourceId,
1325+
const ModuleDependencyID &sinkId) {
1326+
auto startIt = std::find(openSet.begin(), openSet.end(), sourceId);
13231327
assert(startIt != openSet.end());
13241328
std::vector<ModuleDependencyID> cycleNodes(startIt, openSet.end());
1325-
cycleNodes.push_back(*startIt);
1329+
cycleNodes.push_back(sinkId);
13261330
llvm::SmallString<64> errorBuffer;
13271331
emitModulePath(cycleNodes, errorBuffer);
13281332
instance.getASTContext().Diags.diagnose(
@@ -1361,13 +1365,20 @@ static bool diagnoseCycle(CompilerInstance &instance,
13611365
auto beforeSize = openSet.size();
13621366
assert(cache.findDependency(lastOpen).has_value() &&
13631367
"Missing dependency info during cycle diagnosis.");
1364-
for (const auto &dep : cache.getAllDependencies(lastOpen)) {
1365-
if (closeSet.count(dep))
1368+
for (const auto &depId : cache.getAllDependencies(lastOpen)) {
1369+
if (closeSet.count(depId))
13661370
continue;
1367-
if (openSet.insert(dep)) {
1371+
// Ensure we detect dependency of the Source target
1372+
// on an existing Swift module with the same name
1373+
if (kindIsSwiftDependency(depId) &&
1374+
depId.ModuleName == mainId.ModuleName && openSet.contains(mainId)) {
1375+
emitCycleDiagnostic(mainId, depId);
1376+
return true;
1377+
}
1378+
if (openSet.insert(depId)) {
13681379
break;
13691380
} else {
1370-
emitCycleDiagnostic(dep);
1381+
emitCycleDiagnostic(depId, depId);
13711382
return true;
13721383
}
13731384
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/module-cache)
3+
4+
// RUN: not %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -module-name CycleOverlay &> %t/out.txt
5+
6+
// RUN: %FileCheck %s < %t/out.txt
7+
8+
// CHECK: module dependency cycle: 'CycleOverlay (Source Target) -> CycleSwiftMiddle.swiftinterface -> CycleOverlay.swiftinterface'
9+
// CHECK: Swift Overlay dependency of 'CycleSwiftMiddle' on 'CycleOverlay' via Clang module dependency: 'CycleSwiftMiddle.swiftinterface -> CycleClangMiddle.pcm -> CycleOverlay.pcm'
10+
11+
import CycleSwiftMiddle
12+
13+

0 commit comments

Comments
 (0)