[Lldb-commits] [lldb] 1ba6ec0 - [lldb][DWARFASTParserClang] Correctly resolve imported namespaces during expression evaluation

Michael Buch via lldb-commits lldb-commits at lists.llvm.org
Thu Feb 9 17:34:27 PST 2023


Author: Michael Buch
Date: 2023-02-10T01:33:52Z
New Revision: 1ba6ec0ba906472661506ef7bd2f0bf4efe4657e

URL: https://github.com/llvm/llvm-project/commit/1ba6ec0ba906472661506ef7bd2f0bf4efe4657e
DIFF: https://github.com/llvm/llvm-project/commit/1ba6ec0ba906472661506ef7bd2f0bf4efe4657e.diff

LOG: [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

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

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 4429b4fcae2a0..717456698eb23 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -3304,6 +3304,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;
@@ -3465,6 +3470,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/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..9d014dac02648
--- /dev/null
+++ b/lldb/test/API/commands/expression/namespace-alias/TestInlineNamespaceAlias.py
@@ -0,0 +1,29 @@
+"""
+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 test(self):
+        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")

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