Skip to content

Commit 1ba6ec0

Browse files
committed
[lldb][DWARFASTParserClang] Correctly resolve imported namespaces during expression evaluation
**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
1 parent ccee9b7 commit 1ba6ec0

File tree

5 files changed

+105
-0
lines changed

5 files changed

+105
-0
lines changed

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

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

3307+
case DW_TAG_imported_declaration:
3308+
decl_ctx = ResolveImportedDeclarationDIE(die);
3309+
try_parsing_type = false;
3310+
break;
3311+
33073312
case DW_TAG_lexical_block:
33083313
decl_ctx = GetDeclContextForBlock(die);
33093314
try_parsing_type = false;
@@ -3465,6 +3470,42 @@ DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {
34653470
return nullptr;
34663471
}
34673472

3473+
clang::NamespaceDecl *
3474+
DWARFASTParserClang::ResolveImportedDeclarationDIE(const DWARFDIE &die) {
3475+
assert(die && die.Tag() == DW_TAG_imported_declaration);
3476+
3477+
// See if we cached a NamespaceDecl for this imported declaration
3478+
// already
3479+
auto it = m_die_to_decl_ctx.find(die.GetDIE());
3480+
if (it != m_die_to_decl_ctx.end())
3481+
return static_cast<clang::NamespaceDecl *>(it->getSecond());
3482+
3483+
clang::NamespaceDecl *namespace_decl = nullptr;
3484+
3485+
const DWARFDIE imported_uid =
3486+
die.GetAttributeValueAsReferenceDIE(DW_AT_import);
3487+
if (!imported_uid)
3488+
return nullptr;
3489+
3490+
switch (imported_uid.Tag()) {
3491+
case DW_TAG_imported_declaration:
3492+
namespace_decl = ResolveImportedDeclarationDIE(imported_uid);
3493+
break;
3494+
case DW_TAG_namespace:
3495+
namespace_decl = ResolveNamespaceDIE(imported_uid);
3496+
break;
3497+
default:
3498+
return nullptr;
3499+
}
3500+
3501+
if (!namespace_decl)
3502+
return nullptr;
3503+
3504+
LinkDeclContextToDIE(namespace_decl, die);
3505+
3506+
return namespace_decl;
3507+
}
3508+
34683509
clang::DeclContext *DWARFASTParserClang::GetClangDeclContextContainingDIE(
34693510
const DWARFDIE &die, DWARFDIE *decl_ctx_die_copy) {
34703511
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
@@ -132,6 +132,17 @@ class DWARFASTParserClang : public DWARFASTParser {
132132

133133
clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die);
134134

135+
/// Returns the namespace decl that a DW_TAG_imported_declaration imports.
136+
///
137+
/// \param[in] die The import declaration to resolve. If the DIE is not a
138+
/// DW_TAG_imported_declaration the behaviour is undefined.
139+
///
140+
/// \returns The decl corresponding to the namespace that the specified
141+
/// 'die' imports. If the imported entity is not a namespace
142+
/// or another import declaration, returns nullptr. If an error
143+
/// occurs, returns nullptr.
144+
clang::NamespaceDecl *ResolveImportedDeclarationDIE(const DWARFDIE &die);
145+
135146
bool ParseTemplateDIE(const DWARFDIE &die,
136147
lldb_private::TypeSystemClang::TemplateParameterInfos
137148
&template_param_infos);
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: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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 test(self):
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")
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)