Skip to content

Commit 0d47fa0

Browse files
🍒[lldb][SymbolFileDWARF] Fall back to using parent DW_AT_LLVM_include_path for submodules (#10764)
* [lldb][SymbolFileDWARF] Fall back to using parent DW_AT_LLVM_include_path for submodules (llvm#142044) Inferred submodule declarations are emitted in DWARF as `DW_TAG_module`s without `DW_AT_LLVM_include_path`s. Instead the parent DIE will have the include path. This patch adds support for such setups. Without this, the `ClangModulesDeclVendor` would fail to `AddModule` the submodules (i.e., compile and load the submodules). This would cause errors such as: ``` note: error: Header search couldn't locate module 'TopLevel' ``` The test added here also tests llvm#141220. Without that patch we'd fail with: ``` note: error: No module map file in /Users/jonas/Git/llvm-worktrees/llvm-project/lldb/test/API/lang/cpp/decl-from-submodule ``` Unfortunately the embedded clang instance doesn't allow us to use the decls we find in the modules. But we'll try to fix that in a separate patch. rdar://151022173 (cherry picked from commit 7b96272) * [lldb][test] Disable DeclFromSubmodule test on Windows Or more precisely, when linking with link.exe, but Windows is our closest proxy for that right now. This test requires the DWARF info to work, on the Windows on Arm buildbot it fails: ``` AssertionError: Ran command: "expr func(1, 2)" Got output: error: <user expression 0>:1:1: use of undeclared identifier 'func' 1 | func(1, 2) | ^~~~ Expecting start string: "error: <user expression 0>:1:1: 'func' has unknown return type" (was not found) ``` (cherry picked from commit 7a66b28) --------- Co-authored-by: David Spickett <[email protected]>
1 parent 1757c9e commit 0d47fa0

File tree

7 files changed

+60
-2
lines changed

7 files changed

+60
-2
lines changed

‎lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,17 +1221,25 @@ bool SymbolFileDWARF::ParseImportedModules(
12211221
SourceModule module;
12221222
module.path.push_back(ConstString(name));
12231223

1224+
const char *include_path = module_die.GetAttributeValueAsString(
1225+
DW_AT_LLVM_include_path, nullptr);
12241226
DWARFDIE parent_die = module_die;
12251227
while ((parent_die = parent_die.GetParent())) {
12261228
if (parent_die.Tag() != DW_TAG_module)
12271229
break;
12281230
if (const char *name =
12291231
parent_die.GetAttributeValueAsString(DW_AT_name, nullptr))
12301232
module.path.push_back(ConstString(name));
1233+
1234+
// Inferred submodule declarations may not have a
1235+
// DW_AT_LLVM_include_path. Pick the parent (aka umbrella) module's
1236+
// include path instead.
1237+
if (!include_path)
1238+
include_path = parent_die.GetAttributeValueAsString(
1239+
DW_AT_LLVM_include_path, nullptr);
12311240
}
12321241
std::reverse(module.path.begin(), module.path.end());
1233-
if (const char *include_path = module_die.GetAttributeValueAsString(
1234-
DW_AT_LLVM_include_path, nullptr)) {
1242+
if (include_path) {
12351243
FileSpec include_spec(include_path, dwarf_cu->GetPathStyle());
12361244
MakeAbsoluteAndRemap(include_spec, *dwarf_cu,
12371245
m_objfile_sp->GetModule());
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CXX_SOURCES := main.cpp
2+
CXXFLAGS_EXTRAS = $(MANDATORY_MODULE_BUILD_CFLAGS)
3+
4+
include Makefile.rules
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""Test that decl lookup into submodules in C++ works as expected."""
2+
3+
import lldb
4+
import shutil
5+
6+
from lldbsuite.test.decorators import *
7+
from lldbsuite.test.lldbtest import *
8+
from lldbsuite.test import lldbutil
9+
10+
11+
class DeclFromSubmoduleTestCase(TestBase):
12+
# Requires DWARF debug info which is not retained when linking with link.exe.
13+
@skipIfWindows
14+
def test_expr(self):
15+
self.build()
16+
lldbutil.run_to_source_breakpoint(self, "return 0", lldb.SBFileSpec("main.cpp"))
17+
18+
# FIXME: LLDB finds the decl for 'func' in the submodules correctly and hands it to Clang
19+
# but Sema rejects using the decl during name lookup because it is not marked "Visible".
20+
# However, this assertions still ensures that we at least don't fail to compile the
21+
# submodule (which would cause other errors to appear before the expression error, hence
22+
# we use "startstr").
23+
self.expect(
24+
"expr func(1, 2)",
25+
error=True,
26+
startstr="error: <user expression 0>:1:1: 'func' has unknown return type",
27+
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// nodebug to force LLDB to find the decls in modules
2+
[[gnu::nodebug]] inline int func(int x) { return x; }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// nodebug to force LLDB to find the decls in modules
2+
[[gnu::nodebug]] inline int func(int x, int y) { return x + y; }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "TopLevel/module1.h"
2+
#include "TopLevel/module2.h"
3+
4+
int main() {
5+
func(1);
6+
func(2, 3);
7+
8+
return 0;
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module TopLevel {
2+
umbrella "TopLevel"
3+
explicit module * {
4+
export *
5+
}
6+
}

0 commit comments

Comments
 (0)