Skip to content

Commit 7b96272

Browse files
authored
[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
1 parent e4ed718 commit 7b96272

File tree

7 files changed

+58
-2
lines changed

7 files changed

+58
-2
lines changed

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

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

1191+
const char *include_path = module_die.GetAttributeValueAsString(
1192+
DW_AT_LLVM_include_path, nullptr);
11911193
DWARFDIE parent_die = module_die;
11921194
while ((parent_die = parent_die.GetParent())) {
11931195
if (parent_die.Tag() != DW_TAG_module)
11941196
break;
11951197
if (const char *name =
11961198
parent_die.GetAttributeValueAsString(DW_AT_name, nullptr))
11971199
module.path.push_back(ConstString(name));
1200+
1201+
// Inferred submodule declarations may not have a
1202+
// DW_AT_LLVM_include_path. Pick the parent (aka umbrella) module's
1203+
// include path instead.
1204+
if (!include_path)
1205+
include_path = parent_die.GetAttributeValueAsString(
1206+
DW_AT_LLVM_include_path, nullptr);
11981207
}
11991208
std::reverse(module.path.begin(), module.path.end());
1200-
if (const char *include_path = module_die.GetAttributeValueAsString(
1201-
DW_AT_LLVM_include_path, nullptr)) {
1209+
if (include_path) {
12021210
FileSpec include_spec(include_path, dwarf_cu->GetPathStyle());
12031211
MakeAbsoluteAndRemap(include_spec, *dwarf_cu,
12041212
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: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
def test_expr(self):
13+
self.build()
14+
lldbutil.run_to_source_breakpoint(self, "return 0", lldb.SBFileSpec("main.cpp"))
15+
16+
# FIXME: LLDB finds the decl for 'func' in the submodules correctly and hands it to Clang
17+
# but Sema rejects using the decl during name lookup because it is not marked "Visible".
18+
# However, this assertions still ensures that we at least don't fail to compile the
19+
# submodule (which would cause other errors to appear before the expression error, hence
20+
# we use "startstr").
21+
self.expect(
22+
"expr func(1, 2)",
23+
error=True,
24+
startstr="error: <user expression 0>:1:1: 'func' has unknown return type",
25+
)
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)