Skip to content

Commit de77ee5

Browse files
committed
Reland "[lldb][DWARFASTParserClang] Correctly resolve imported namespaces during expression evaluation"
This relands a patch previously reverted in `181d6e24ca3c09bfd6ec7c3b20affde3e5ea9b40`. This wasn't quite working on Linux because we weren't populating the manual DWARF index with `DW_TAG_imported_declaration`. The relanded patch does this. **Summary** This patch makes the expression evaluator understand namespace aliases. This will become important once `std::ranges` become more widespread since `std::views` is defined as: ``` namespace std { namespace ranges::views {} namespace views = ranges::views; } ``` **Testing** * Added API test Differential Revision: https://reviews.llvm.org/D143398 (cherry picked from commit 6e10e6c)
1 parent a8d15ea commit de77ee5

File tree

6 files changed

+115
-0
lines changed

6 files changed

+115
-0
lines changed

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3266,6 +3266,11 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {
32663266
try_parsing_type = false;
32673267
break;
32683268

3269+
case DW_TAG_imported_declaration:
3270+
decl_ctx = ResolveImportedDeclarationDIE(die);
3271+
try_parsing_type = false;
3272+
break;
3273+
32693274
case DW_TAG_lexical_block:
32703275
decl_ctx = GetDeclContextForBlock(die);
32713276
try_parsing_type = false;
@@ -3428,6 +3433,42 @@ DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {
34283433
return nullptr;
34293434
}
34303435

3436+
clang::NamespaceDecl *
3437+
DWARFASTParserClang::ResolveImportedDeclarationDIE(const DWARFDIE &die) {
3438+
assert(die && die.Tag() == DW_TAG_imported_declaration);
3439+
3440+
// See if we cached a NamespaceDecl for this imported declaration
3441+
// already
3442+
auto it = m_die_to_decl_ctx.find(die.GetDIE());
3443+
if (it != m_die_to_decl_ctx.end())
3444+
return static_cast<clang::NamespaceDecl *>(it->getSecond());
3445+
3446+
clang::NamespaceDecl *namespace_decl = nullptr;
3447+
3448+
const DWARFDIE imported_uid =
3449+
die.GetAttributeValueAsReferenceDIE(DW_AT_import);
3450+
if (!imported_uid)
3451+
return nullptr;
3452+
3453+
switch (imported_uid.Tag()) {
3454+
case DW_TAG_imported_declaration:
3455+
namespace_decl = ResolveImportedDeclarationDIE(imported_uid);
3456+
break;
3457+
case DW_TAG_namespace:
3458+
namespace_decl = ResolveNamespaceDIE(imported_uid);
3459+
break;
3460+
default:
3461+
return nullptr;
3462+
}
3463+
3464+
if (!namespace_decl)
3465+
return nullptr;
3466+
3467+
LinkDeclContextToDIE(namespace_decl, die);
3468+
3469+
return namespace_decl;
3470+
}
3471+
34313472
clang::DeclContext *DWARFASTParserClang::GetClangDeclContextContainingDIE(
34323473
const DWARFDIE &die, DWARFDIE *decl_ctx_die_copy) {
34333474
SymbolFileDWARF *dwarf = die.GetDWARF();

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,17 @@ class DWARFASTParserClang : public DWARFASTParser {
118118

119119
clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die);
120120

121+
/// Returns the namespace decl that a DW_TAG_imported_declaration imports.
122+
///
123+
/// \param[in] die The import declaration to resolve. If the DIE is not a
124+
/// DW_TAG_imported_declaration the behaviour is undefined.
125+
///
126+
/// \returns The decl corresponding to the namespace that the specified
127+
/// 'die' imports. If the imported entity is not a namespace
128+
/// or another import declaration, returns nullptr. If an error
129+
/// occurs, returns nullptr.
130+
clang::NamespaceDecl *ResolveImportedDeclarationDIE(const DWARFDIE &die);
131+
121132
bool ParseTemplateDIE(const DWARFDIE &die,
122133
lldb_private::TypeSystemClang::TemplateParameterInfos
123134
&template_param_infos);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
207207
case DW_TAG_enumeration_type:
208208
case DW_TAG_inlined_subroutine:
209209
case DW_TAG_namespace:
210+
case DW_TAG_imported_declaration:
210211
case DW_TAG_string_type:
211212
case DW_TAG_structure_type:
212213
case DW_TAG_subprogram:
@@ -353,6 +354,7 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
353354
break;
354355

355356
case DW_TAG_namespace:
357+
case DW_TAG_imported_declaration:
356358
if (name)
357359
set.namespaces.Insert(ConstString(name), ref);
358360
break;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CXX_SOURCES := main.cpp
2+
3+
include Makefile.rules
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
Test that we correctly handle namespace
3+
expression evaluation through namespace
4+
aliases.
5+
"""
6+
7+
import lldb
8+
9+
from lldbsuite.test.decorators import *
10+
from lldbsuite.test.lldbtest import *
11+
from lldbsuite.test import lldbutil
12+
13+
class TestInlineNamespace(TestBase):
14+
def do_test(self, params):
15+
self.build()
16+
17+
lldbutil.run_to_source_breakpoint(self,
18+
"return A::B::C::a", lldb.SBFileSpec("main.cpp"))
19+
20+
self.expect_expr("A::C::a", result_type="int", result_value="-1")
21+
self.expect_expr("A::D::a", result_type="int", result_value="-1")
22+
23+
self.expect_expr("A::C::func()", result_type="int", result_value="0")
24+
self.expect_expr("A::D::func()", result_type="int", result_value="0")
25+
26+
self.expect_expr("E::C::a", result_type="int", result_value="-1")
27+
self.expect_expr("E::D::a", result_type="int", result_value="-1")
28+
self.expect_expr("F::a", result_type="int", result_value="-1")
29+
self.expect_expr("G::a", result_type="int", result_value="-1")
30+
31+
@skipIf(debug_info=no_match(["dsym"]))
32+
def test_dsym(self):
33+
self.do_test({})
34+
35+
@skipIf(debug_info="dsym")
36+
def test_dwarf(self):
37+
self.do_test(dict(CFLAGS_EXTRAS="-gdwarf-5 -gpubnames"))
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace A {
2+
inline namespace _A {
3+
namespace B {
4+
namespace C {
5+
int a = -1;
6+
7+
int func() { return 0; }
8+
} // namespace C
9+
} // namespace B
10+
11+
namespace C = B::C;
12+
namespace D = B::C;
13+
14+
} // namespace _A
15+
} // namespace A
16+
17+
namespace E = A;
18+
namespace F = E::C;
19+
namespace G = F;
20+
21+
int main(int argc, char **argv) { return A::B::C::a; }

0 commit comments

Comments
 (0)