Skip to content

Commit 2abff47

Browse files
authored
[lldb] Fallback to implicit modules when explicit modules are missing (llvm#8356)
Handle the case where an explicit module path does not exist, by falling back to implicit modules. The initial logic is: If any one explicit module is nonexistent, then remove all references to explicit modules. Additionally, remove all explicit module maps.
1 parent 6e0b031 commit 2abff47

File tree

4 files changed

+87
-0
lines changed

4 files changed

+87
-0
lines changed

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,15 @@
5757
#include "clang/Driver/Driver.h"
5858

5959
#include "llvm/ADT/ArrayRef.h"
60+
#include "llvm/ADT/STLExtras.h"
6061
#include "llvm/ADT/StringRef.h"
6162
#include "llvm/ADT/StringSet.h"
6263
#include "llvm/CodeGen/TargetSubtargetInfo.h"
6364
#include "llvm/IR/DataLayout.h"
6465
#include "llvm/IR/LLVMContext.h"
6566
#include "llvm/IR/Module.h"
6667
#include "llvm/MC/TargetRegistry.h"
68+
#include "llvm/Support/FileSystem.h"
6769
#include "llvm/Support/MemoryBuffer.h"
6870
#include "llvm/Support/Path.h"
6971
#include "llvm/Support/TargetSelect.h"
@@ -1594,9 +1596,50 @@ void SwiftASTContext::AddExtraClangArgs(const std::vector<std::string> &source,
15941596
}
15951597
}
15961598

1599+
namespace {
1600+
1601+
bool HasNonexistentExplicitModule(const std::vector<std::string> &args) {
1602+
for (const std::string &arg : args) {
1603+
StringRef value = arg;
1604+
if (!value.consume_front("-fmodule-file="))
1605+
continue;
1606+
StringRef path = value;
1607+
size_t eq = value.find('=');
1608+
// The value that follows is in one of two formats:
1609+
// 1. ModuleName=ModulePath
1610+
// 2. ModulePath
1611+
if (eq != std::string::npos)
1612+
// The value appears to be in ModuleName=ModulePath forat.
1613+
path = value.drop_front(eq + 1);
1614+
// Check both path and value. This is to handle paths containing '='.
1615+
if (!llvm::sys::fs::exists(path) && !llvm::sys::fs::exists(value)) {
1616+
std::string m_description;
1617+
HEALTH_LOG_PRINTF("Nonexistent explicit module file %s", arg.data());
1618+
return true;
1619+
}
1620+
}
1621+
return false;
1622+
}
1623+
1624+
void RemoveExplicitModules(std::vector<std::string> &args) {
1625+
llvm::erase_if(args, [](const std::string &arg) {
1626+
if (arg == "-fno-implicit-modules" || arg == "-fno-implicit-module-maps")
1627+
return true;
1628+
StringRef s = arg;
1629+
if (s.starts_with("-fmodule-file=") || s.starts_with("-fmodule-map-file="))
1630+
return true;
1631+
1632+
return false;
1633+
});
1634+
}
1635+
1636+
} // namespace
1637+
15971638
void SwiftASTContext::AddExtraClangArgs(const std::vector<std::string> &ExtraArgs) {
15981639
swift::ClangImporterOptions &importer_options = GetClangImporterOptions();
15991640
AddExtraClangArgs(ExtraArgs, importer_options.ExtraArgs);
1641+
if (HasNonexistentExplicitModule(importer_options.ExtraArgs))
1642+
RemoveExplicitModules(importer_options.ExtraArgs);
16001643
}
16011644

16021645
void SwiftASTContext::AddUserClangArgs(TargetProperties &props) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFT_ENABLE_EXPLICIT_MODULES := YES
3+
USE_PRIVATE_MODULE_CACHE := YES
4+
include Makefile.rules
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import shutil
2+
import lldb
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbtest as lldbtest
5+
import lldbsuite.test.lldbutil as lldbutil
6+
7+
8+
class TestCase(lldbtest.TestBase):
9+
@swiftTest
10+
@skipIf(oslist=["linux"], bugnumber="rdar://124691219")
11+
def test_missing_explicit_modules(self):
12+
"""Test missing explicit Swift modules and fallback to implicit modules."""
13+
self.build()
14+
15+
# This test verifies the case where explicit modules are missing.
16+
# Remove explicit modules from their place in the module cache.
17+
mod_cache = self.getBuildArtifact("private-module-cache")
18+
shutil.rmtree(mod_cache)
19+
20+
lldbutil.run_to_source_breakpoint(
21+
self, "Set breakpoint here", lldb.SBFileSpec("main.swift")
22+
)
23+
24+
log = self.getBuildArtifact("types.log")
25+
self.runCmd(f"log enable lldb types -f '{log}'")
26+
27+
self.expect("expression c", substrs=["hello implicit fallback"])
28+
29+
self.filecheck(f"platform shell cat {log}", __file__)
30+
# CHECK: Nonexistent explicit module file
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class Class {
2+
var msg : String = "hello implicit fallback"
3+
}
4+
5+
func main() {
6+
let c = Class()
7+
print(c) // Set breakpoint here
8+
}
9+
10+
main()

0 commit comments

Comments
 (0)