[Lldb-commits] [lldb] 6e10e6c - Reland "[lldb][DWARFASTParserClang] Correctly resolve imported namespaces during expression evaluation"
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Mon Feb 13 08:59:06 PST 2023
Author: Michael Buch
Date: 2023-02-13T16:58:05Z
New Revision: 6e10e6cb8fab015952edbc86d82e85b991ad26dc
URL: https://github.com/llvm/llvm-project/commit/6e10e6cb8fab015952edbc86d82e85b991ad26dc
DIFF: https://github.com/llvm/llvm-project/commit/6e10e6cb8fab015952edbc86d82e85b991ad26dc.diff
LOG: 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
Added:
lldb/test/API/commands/expression/namespace-alias/Makefile
lldb/test/API/commands/expression/namespace-alias/TestInlineNamespaceAlias.py
lldb/test/API/commands/expression/namespace-alias/main.cpp
Modified:
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
Removed:
################################################################################
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 8401d648c6704..9a7fa415c4376 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -3347,6 +3347,11 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {
try_parsing_type = false;
break;
+ case DW_TAG_imported_declaration:
+ decl_ctx = ResolveImportedDeclarationDIE(die);
+ try_parsing_type = false;
+ break;
+
case DW_TAG_lexical_block:
decl_ctx = GetDeclContextForBlock(die);
try_parsing_type = false;
@@ -3508,6 +3513,42 @@ DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {
return nullptr;
}
+clang::NamespaceDecl *
+DWARFASTParserClang::ResolveImportedDeclarationDIE(const DWARFDIE &die) {
+ assert(die && die.Tag() == DW_TAG_imported_declaration);
+
+ // See if we cached a NamespaceDecl for this imported declaration
+ // already
+ auto it = m_die_to_decl_ctx.find(die.GetDIE());
+ if (it != m_die_to_decl_ctx.end())
+ return static_cast<clang::NamespaceDecl *>(it->getSecond());
+
+ clang::NamespaceDecl *namespace_decl = nullptr;
+
+ const DWARFDIE imported_uid =
+ die.GetAttributeValueAsReferenceDIE(DW_AT_import);
+ if (!imported_uid)
+ return nullptr;
+
+ switch (imported_uid.Tag()) {
+ case DW_TAG_imported_declaration:
+ namespace_decl = ResolveImportedDeclarationDIE(imported_uid);
+ break;
+ case DW_TAG_namespace:
+ namespace_decl = ResolveNamespaceDIE(imported_uid);
+ break;
+ default:
+ return nullptr;
+ }
+
+ if (!namespace_decl)
+ return nullptr;
+
+ LinkDeclContextToDIE(namespace_decl, die);
+
+ return namespace_decl;
+}
+
clang::DeclContext *DWARFASTParserClang::GetClangDeclContextContainingDIE(
const DWARFDIE &die, DWARFDIE *decl_ctx_die_copy) {
SymbolFileDWARF *dwarf = die.GetDWARF();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 0733d22a0069b..a4613afafd54f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -132,6 +132,17 @@ class DWARFASTParserClang : public DWARFASTParser {
clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die);
+ /// Returns the namespace decl that a DW_TAG_imported_declaration imports.
+ ///
+ /// \param[in] die The import declaration to resolve. If the DIE is not a
+ /// DW_TAG_imported_declaration the behaviour is undefined.
+ ///
+ /// \returns The decl corresponding to the namespace that the specified
+ /// 'die' imports. If the imported entity is not a namespace
+ /// or another import declaration, returns nullptr. If an error
+ /// occurs, returns nullptr.
+ clang::NamespaceDecl *ResolveImportedDeclarationDIE(const DWARFDIE &die);
+
bool ParseTemplateDIE(const DWARFDIE &die,
lldb_private::TypeSystemClang::TemplateParameterInfos
&template_param_infos);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 90ac5afb179a3..50c495d4ac962 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -208,6 +208,7 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
case DW_TAG_enumeration_type:
case DW_TAG_inlined_subroutine:
case DW_TAG_namespace:
+ case DW_TAG_imported_declaration:
case DW_TAG_string_type:
case DW_TAG_structure_type:
case DW_TAG_subprogram:
@@ -354,6 +355,7 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
break;
case DW_TAG_namespace:
+ case DW_TAG_imported_declaration:
if (name)
set.namespaces.Insert(ConstString(name), ref);
break;
diff --git a/lldb/test/API/commands/expression/namespace-alias/Makefile b/lldb/test/API/commands/expression/namespace-alias/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/commands/expression/namespace-alias/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/commands/expression/namespace-alias/TestInlineNamespaceAlias.py b/lldb/test/API/commands/expression/namespace-alias/TestInlineNamespaceAlias.py
new file mode 100644
index 0000000000000..0c3f3d457f254
--- /dev/null
+++ b/lldb/test/API/commands/expression/namespace-alias/TestInlineNamespaceAlias.py
@@ -0,0 +1,37 @@
+"""
+Test that we correctly handle namespace
+expression evaluation through namespace
+aliases.
+"""
+
+import lldb
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestInlineNamespace(TestBase):
+ def do_test(self, params):
+ self.build()
+
+ lldbutil.run_to_source_breakpoint(self,
+ "return A::B::C::a", lldb.SBFileSpec("main.cpp"))
+
+ self.expect_expr("A::C::a", result_type="int", result_value="-1")
+ self.expect_expr("A::D::a", result_type="int", result_value="-1")
+
+ self.expect_expr("A::C::func()", result_type="int", result_value="0")
+ self.expect_expr("A::D::func()", result_type="int", result_value="0")
+
+ self.expect_expr("E::C::a", result_type="int", result_value="-1")
+ self.expect_expr("E::D::a", result_type="int", result_value="-1")
+ self.expect_expr("F::a", result_type="int", result_value="-1")
+ self.expect_expr("G::a", result_type="int", result_value="-1")
+
+ @skipIf(debug_info=no_match(["dsym"]))
+ def test_dsym(self):
+ self.do_test({})
+
+ @skipIf(debug_info="dsym")
+ def test_dwarf(self):
+ self.do_test(dict(CFLAGS_EXTRAS="-gdwarf-5 -gpubnames"))
diff --git a/lldb/test/API/commands/expression/namespace-alias/main.cpp b/lldb/test/API/commands/expression/namespace-alias/main.cpp
new file mode 100644
index 0000000000000..b35efda11c8cf
--- /dev/null
+++ b/lldb/test/API/commands/expression/namespace-alias/main.cpp
@@ -0,0 +1,21 @@
+namespace A {
+inline namespace _A {
+namespace B {
+namespace C {
+int a = -1;
+
+int func() { return 0; }
+} // namespace C
+} // namespace B
+
+namespace C = B::C;
+namespace D = B::C;
+
+} // namespace _A
+} // namespace A
+
+namespace E = A;
+namespace F = E::C;
+namespace G = F;
+
+int main(int argc, char **argv) { return A::B::C::a; }
More information about the lldb-commits
mailing list