Skip to content

Conversation

@Michael137
Copy link
Member

@Michael137 Michael137 commented Dec 1, 2025

Depends on:

We keep repeating the boilerplate of creating a DWARFASTParserClangStub and TypeSystemClangHolder in all the unit-test cases. Lets extract this into a helper to make the tests easier to grok.

We actually only need the DWARFASTParserClangStub and a TypeSystemClangHolder in one of the test cases. For the rest, we can just re-use the typesystem/parser that the YAMLModuleTester created. Re-using them makes it more straightforward to write test-cases because we don't need to worry about which TypeSystem which DWARFParser created types into.

@llvmbot
Copy link
Member

llvmbot commented Dec 1, 2025

@llvm/pr-subscribers-lldb

Author: Michael Buch (Michael137)

Changes

We keep repeating the boilerplate of creating a DWARFASTParserClangStub and TypeSystemClangHolder in all the unit-test cases. Lets extract this into a helper to make the tests easier to grok.


Full diff: https://github.com/llvm/llvm-project/pull/170132.diff

1 Files Affected:

  • (modified) lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp (+111-182)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index cef3a25a4a960..bd7aed8d8c2aa 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -42,6 +42,46 @@ class DWARFASTParserClangStub : public DWARFASTParserClang {
     return keys;
   }
 };
+
+/// Helper structure for DWARFASTParserClang tests that want to parse DWARF
+/// generated using yaml2obj. On construction parses the supplied YAML data
+/// into a DWARF module and creates a DWARFASTParserClang and TypeSystem that
+/// live for the duration of this object.
+class DWARFASTParserClangYAMLTester {
+public:
+  DWARFASTParserClangYAMLTester(llvm::StringRef yaml_data)
+      : m_module_tester(yaml_data),
+        m_ast_holder_up(
+            std::make_unique<clang_utils::TypeSystemClangHolder>("ast")),
+        m_stub(*m_ast_holder_up->GetAST()) {}
+
+  DWARFDIE GetCUDIE() {
+    DWARFUnit *unit = m_module_tester.GetDwarfUnit();
+    assert(unit);
+
+    const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
+    assert(cu_entry->Tag() == DW_TAG_compile_unit);
+
+    return DWARFDIE(unit, cu_entry);
+  }
+
+  DWARFASTParserClangStub &GetParser() { return m_stub; }
+
+  TypeSystemClang &GetTypeSystem() {
+    assert(m_ast_holder_up);
+
+    TypeSystemClang *ts = m_ast_holder_up->GetAST();
+
+    assert(ts);
+
+    return *ts;
+  }
+
+private:
+  YAMLModuleTester m_module_tester;
+  std::unique_ptr<clang_utils::TypeSystemClangHolder> m_ast_holder_up;
+  DWARFASTParserClangStub m_stub;
+};
 } // namespace
 
 // If your implementation needs to dereference the dummy pointers we are
@@ -100,23 +140,15 @@ TEST_F(DWARFASTParserClangTests,
         - AbbrCode:        0x00000000
 )";
 
-  YAMLModuleTester t(yamldata);
-  ASSERT_TRUE((bool)t.GetDwarfUnit());
-
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
+  DWARFASTParserClangYAMLTester tester(yamldata);
+  DWARFASTParserClangStub &ast_parser = tester.GetParser();
 
-  DWARFASTParserClangStub ast_parser(ast_ctx);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE();
-  const DWARFDebugInfoEntry *die_child0 = die_first->GetFirstChild();
-  const DWARFDebugInfoEntry *die_child1 = die_child0->GetSibling();
-  const DWARFDebugInfoEntry *die_child2 = die_child1->GetSibling();
-  const DWARFDebugInfoEntry *die_child3 = die_child2->GetSibling();
-  std::vector<DWARFDIE> dies = {
-      DWARFDIE(unit, die_child0), DWARFDIE(unit, die_child1),
-      DWARFDIE(unit, die_child2), DWARFDIE(unit, die_child3)};
+  DWARFDIE die_first = tester.GetCUDIE();
+  DWARFDIE die_child0 = die_first.GetFirstChild();
+  DWARFDIE die_child1 = die_child0.GetSibling();
+  DWARFDIE die_child2 = die_child1.GetSibling();
+  DWARFDIE die_child3 = die_child2.GetSibling();
+  std::vector<DWARFDIE> dies = {die_child0, die_child1, die_child2, die_child3};
   std::vector<clang::DeclContext *> decl_ctxs = {
       (clang::DeclContext *)1LL, (clang::DeclContext *)2LL,
       (clang::DeclContext *)2LL, (clang::DeclContext *)3LL};
@@ -248,17 +280,9 @@ TEST_F(DWARFASTParserClangTests, TestCallingConventionParsing) {
         - AbbrCode:        0x0
 ...
 )";
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  DWARFDIE cu_die(unit, cu_entry);
+  DWARFASTParserClangYAMLTester tester(yamldata);
 
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   std::vector<std::string> found_function_types;
   // The DWARF above is just a list of functions. Parse all of them to
@@ -267,7 +291,8 @@ TEST_F(DWARFASTParserClangTests, TestCallingConventionParsing) {
     ASSERT_EQ(func.Tag(), DW_TAG_subprogram);
     SymbolContext sc;
     bool new_type = false;
-    lldb::TypeSP type = ast_parser.ParseTypeFromDWARF(sc, func, &new_type);
+    lldb::TypeSP type =
+        tester.GetParser().ParseTypeFromDWARF(sc, func, &new_type);
     found_function_types.push_back(
         type->GetForwardCompilerType().GetTypeName().AsCString());
   }
@@ -394,18 +419,9 @@ TEST_F(DWARFASTParserClangTests, TestPtrAuthParsing) {
         - AbbrCode:        0x00 # end of child tags of 0x0c
 ...
 )";
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  DWARFDIE cu_die(unit, cu_entry);
-
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFASTParserClangYAMLTester tester(yamldata);
 
+  DWARFDIE cu_die = tester.GetCUDIE();
   DWARFDIE ptrauth_variable = cu_die.GetFirstChild();
   ASSERT_EQ(ptrauth_variable.Tag(), DW_TAG_variable);
   DWARFDIE ptrauth_type =
@@ -415,7 +431,7 @@ TEST_F(DWARFASTParserClangTests, TestPtrAuthParsing) {
   SymbolContext sc;
   bool new_type = false;
   lldb::TypeSP type_sp =
-      ast_parser.ParseTypeFromDWARF(sc, ptrauth_type, &new_type);
+      tester.GetParser().ParseTypeFromDWARF(sc, ptrauth_type, &new_type);
   CompilerType compiler_type = type_sp->GetForwardCompilerType();
   ASSERT_EQ(compiler_type.GetPtrAuthKey(), 0U);
   ASSERT_EQ(compiler_type.GetPtrAuthAddressDiversity(), false);
@@ -554,24 +570,17 @@ TEST_F(DWARFASTParserClangTests, TestDefaultTemplateParamParsing) {
   auto BufferOrError = llvm::MemoryBuffer::getFile(
       GetInputFilePath("DW_AT_default_value-test.yaml"), /*IsText=*/true);
   ASSERT_TRUE(BufferOrError);
-  YAMLModuleTester t(BufferOrError.get()->getBuffer());
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  DWARFDIE cu_die(unit, cu_entry);
 
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFASTParserClangYAMLTester tester(BufferOrError.get()->getBuffer());
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   llvm::SmallVector<lldb::TypeSP, 2> types;
   for (DWARFDIE die : cu_die.children()) {
     if (die.Tag() == DW_TAG_class_type) {
       SymbolContext sc;
       bool new_type = false;
-      types.push_back(ast_parser.ParseTypeFromDWARF(sc, die, &new_type));
+      types.push_back(
+          tester.GetParser().ParseTypeFromDWARF(sc, die, &new_type));
     }
   }
 
@@ -605,23 +614,14 @@ TEST_F(DWARFASTParserClangTests, TestSpecDeclExistsError) {
   auto BufferOrError = llvm::MemoryBuffer::getFile(
       GetInputFilePath("DW_AT_spec_decl_exists-test.yaml"), /*IsText=*/true);
   ASSERT_TRUE(BufferOrError);
-  YAMLModuleTester t(BufferOrError.get()->getBuffer());
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  DWARFDIE cu_die(unit, cu_entry);
-
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFASTParserClangYAMLTester tester(BufferOrError.get()->getBuffer());
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   llvm::SmallVector<lldb::TypeSP, 2> specializations;
   for (DWARFDIE die : cu_die.children()) {
     SymbolContext sc;
     bool new_type = false;
-    auto type = ast_parser.ParseTypeFromDWARF(sc, die, &new_type);
+    auto type = tester.GetParser().ParseTypeFromDWARF(sc, die, &new_type);
     llvm::StringRef die_name = llvm::StringRef(die.GetName());
     if (die_name.starts_with("_Optional_payload")) {
       specializations.push_back(std::move(type));
@@ -730,18 +730,8 @@ TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) {
         - AbbrCode:        0x00 # end of child tags of 0x0c
 ...
 )";
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
-  DWARFDIE cu_die(unit, cu_entry);
-
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFASTParserClangYAMLTester tester(yamldata);
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   DWARFDIE decl_die;
   DWARFDIE def_die;
@@ -762,6 +752,8 @@ TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) {
   ParsedDWARFTypeAttributes attrs(def_die);
   ASSERT_TRUE(attrs.decl.IsValid());
 
+  DWARFASTParserClangStub &ast_parser = tester.GetParser();
+
   SymbolContext sc;
   bool new_type = false;
   lldb::TypeSP type_sp = ast_parser.ParseTypeFromDWARF(sc, decl_die, &new_type);
@@ -906,18 +898,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer) {
         - AbbrCode: 0x0
 ...
 )";
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
-  DWARFDIE cu_die(unit, cu_entry);
-
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFASTParserClangYAMLTester tester(yamldata);
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   auto context_die = cu_die.GetFirstChild();
   ASSERT_TRUE(context_die.IsValid());
@@ -932,7 +914,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer) {
     auto param_die = decl_die.GetFirstChild();
     ASSERT_TRUE(param_die.IsValid());
 
-    EXPECT_EQ(param_die, ast_parser.GetObjectParameter(decl_die, context_die));
+    EXPECT_EQ(param_die,
+              tester.GetParser().GetObjectParameter(decl_die, context_die));
   }
 
   {
@@ -945,8 +928,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer) {
     auto param_die = subprogram_definition.GetFirstChild();
     ASSERT_TRUE(param_die.IsValid());
 
-    EXPECT_EQ(param_die, ast_parser.GetObjectParameter(subprogram_definition,
-                                                       context_die));
+    EXPECT_EQ(param_die, tester.GetParser().GetObjectParameter(
+                             subprogram_definition, context_die));
   }
 }
 
@@ -1076,18 +1059,8 @@ TEST_F(DWARFASTParserClangTests,
         - AbbrCode: 0x0
 ...
 )";
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
-  DWARFDIE cu_die(unit, cu_entry);
-
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFASTParserClangYAMLTester tester(yamldata);
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   auto context_die = cu_die.GetFirstChild();
   ASSERT_TRUE(context_die.IsValid());
@@ -1105,7 +1078,7 @@ TEST_F(DWARFASTParserClangTests,
   auto param_die = subprogram_definition.GetFirstChild();
   ASSERT_TRUE(param_die.IsValid());
   EXPECT_EQ(param_die,
-            ast_parser.GetObjectParameter(subprogram_definition, {}));
+            tester.GetParser().GetObjectParameter(subprogram_definition, {}));
 }
 
 TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) {
@@ -1243,14 +1216,8 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) {
         - AbbrCode: 0x0
 ...
 )";
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
-  DWARFDIE cu_die(unit, cu_entry);
+  DWARFASTParserClangYAMLTester tester(yamldata);
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   auto ts_or_err =
       cu_die.GetDWARF()->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
@@ -1419,22 +1386,8 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ParameterCreation) {
         - AbbrCode: 0x0
 ...
 )";
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
-  DWARFDIE cu_die(unit, cu_entry);
-
-  auto ts_or_err =
-      cu_die.GetDWARF()->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
-  ASSERT_TRUE(static_cast<bool>(ts_or_err));
-  llvm::consumeError(ts_or_err.takeError());
-
-  auto *ts = static_cast<TypeSystemClang *>(ts_or_err->get());
-  auto *parser = static_cast<DWARFASTParserClang *>(ts->GetDWARFParser());
+  DWARFASTParserClangYAMLTester tester(yamldata);
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   auto subprogram = cu_die.GetFirstChild();
   ASSERT_TRUE(subprogram.IsValid());
@@ -1442,11 +1395,13 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ParameterCreation) {
 
   SymbolContext sc;
   bool new_type;
-  auto type_sp = parser->ParseTypeFromDWARF(sc, subprogram, &new_type);
+  auto type_sp =
+      tester.GetParser().ParseTypeFromDWARF(sc, subprogram, &new_type);
   ASSERT_NE(type_sp, nullptr);
 
-  auto result = ts->GetTranslationUnitDecl()->lookup(
-      clang_utils::getDeclarationName(*ts, "func"));
+  TypeSystemClang &ts = tester.GetTypeSystem();
+  auto result = ts.GetTranslationUnitDecl()->lookup(
+      clang_utils::getDeclarationName(ts, "func"));
   ASSERT_TRUE(result.isSingleResult());
 
   auto const *func = llvm::cast<clang::FunctionDecl>(result.front());
@@ -1609,19 +1564,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) {
         - AbbrCode: 0x0
 ...
 )";
-
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
-  DWARFDIE cu_die(unit, cu_entry);
-
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFASTParserClangYAMLTester tester(yamldata);
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   auto context_die = cu_die.GetFirstChild();
   ASSERT_TRUE(context_die.IsValid());
@@ -1640,7 +1584,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) {
     auto param_die = sub1.GetFirstChild().GetSibling();
     ASSERT_TRUE(param_die.IsValid());
 
-    EXPECT_EQ(param_die, ast_parser.GetObjectParameter(sub1, context_die));
+    EXPECT_EQ(param_die,
+              tester.GetParser().GetObjectParameter(sub1, context_die));
   }
 
   // Object parameter is at constant index 0
@@ -1648,7 +1593,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) {
     auto param_die = sub2.GetFirstChild();
     ASSERT_TRUE(param_die.IsValid());
 
-    EXPECT_EQ(param_die, ast_parser.GetObjectParameter(sub2, context_die));
+    EXPECT_EQ(param_die,
+              tester.GetParser().GetObjectParameter(sub2, context_die));
   }
 }
 
@@ -1711,19 +1657,8 @@ TEST_F(DWARFASTParserClangTests, TestTypeBitSize) {
             - Value: 0x02
 ...
 )";
-
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
-  DWARFDIE cu_die(unit, cu_entry);
-
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFASTParserClangYAMLTester tester(yamldata);
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   auto type_die = cu_die.GetFirstChild();
   ASSERT_TRUE(type_die.IsValid());
@@ -1734,8 +1669,8 @@ TEST_F(DWARFASTParserClangTests, TestTypeBitSize) {
   EXPECT_EQ(attrs.data_bit_size.value_or(0), 2U);
 
   SymbolContext sc;
-  auto type_sp =
-      ast_parser.ParseTypeFromDWARF(sc, type_die, /*type_is_new_ptr=*/nullptr);
+  auto type_sp = tester.GetParser().ParseTypeFromDWARF(
+      sc, type_die, /*type_is_new_ptr=*/nullptr);
   ASSERT_NE(type_sp, nullptr);
 
   EXPECT_EQ(llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
@@ -1857,27 +1792,17 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
 ...
 
 )";
-
-  YAMLModuleTester t(yamldata);
-
-  DWARFUnit *unit = t.GetDwarfUnit();
-  ASSERT_NE(unit, nullptr);
-  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
-  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
-  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
-  DWARFDIE cu_die(unit, cu_entry);
-
-  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
-  auto &ast_ctx = *holder->GetAST();
-  DWARFASTParserClangStub ast_parser(ast_ctx);
+  DWARFASTParserClangYAMLTester tester(yamldata);
+  DWARFDIE cu_die = tester.GetCUDIE();
 
   auto type_die = cu_die.GetFirstChild();
   ASSERT_TRUE(type_die.IsValid());
 
   {
     SymbolContext sc;
-    auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
-                                                 /*type_is_new_ptr=*/nullptr);
+    auto type_sp =
+        tester.GetParser().ParseTypeFromDWARF(sc, type_die,
+                                              /*type_is_new_ptr=*/nullptr);
     ASSERT_NE(type_sp, nullptr);
 
     EXPECT_EQ(
@@ -1891,8 +1816,9 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
   {
     type_die = type_die.GetSibling();
     SymbolContext sc;
-    auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
-                                                 /*type_is_new_ptr=*/nullptr);
+    auto type_sp =
+        tester.GetParser().ParseTypeFromDWARF(sc, type_die,
+                                              /*type_is_new_ptr=*/nullptr);
     ASSERT_NE(type_sp, nullptr);
 
     EXPECT_EQ(
@@ -1906,8 +1832,9 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
   {
     type_die = type_die.GetSibling();
     SymbolContext sc;
-    auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
-                                                 /*type_is_new_ptr=*/nullptr);
+    auto type_sp =
+        tester.GetParser().ParseTypeFromDWARF(sc, type_die,
+                                              /*type_is_new_ptr=*/nullptr);
     ASSERT_NE(type_sp, nullptr);
 
     EXPECT_EQ(
@@ -1922,8 +1849,9 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
   {
     type_die = type_die.GetSibling();
     SymbolContext sc;
-    auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
-                                                 /*type_is_new_ptr=*/nullptr);
+    auto type_sp =
+        tester.GetParser().ParseTypeFromDWARF(sc, type_die,
+                                              /*type_is_new_ptr=*/nullptr);
     ASSERT_NE(type_sp, nullptr);
 
     EXPECT_EQ(
@@ -1938,8 +1866,9 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
   {
     type_die = type_die.GetSibling();
     SymbolContext sc;
-    auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
-                                                 /*type_is_new_ptr=*/nullptr);
+    auto type_sp =
+        tester.GetParser().ParseTypeFromDWARF(sc, type_die,
+                                              /*type_is_new_ptr=*/nullptr);
     ASSERT_NE(type_sp, nullptr);
 
     EXPECT_EQ(

Michael137 added a commit to Michael137/llvm-project that referenced this pull request Dec 1, 2025
…_TAG_typedef

Depends on:
* llvm#170132

Clang gained the `-gtemplate-alias` not too long ago, which emits C++ alias templates as `DW_TAG_template_alias` (instead of `DW_TAG_typedef`). The main difference is that `DW_TAG_template_alias` has `DW_TAG_template_XXX` children. The flag was not enabled by default because consumers (mainly LLDB) didn't know how to handle it. This patch adds rudimentary support for debugging with `DW_TAG_template_alias`.

This patch simply creates the same kind of `TypedefDecl` as we do for `DW_TAG_typedef`. The more complete solution would be to create a `TypeAliasTemplateDecl` and associated `TypeAliasDecl`. But that would require DWARF to carry generic template information, but currently each `DW_TAG_template_alias` represents a concrete instantiation. We could probably hack up some working AST representation that includes the template parameters, but I currently don't see a compelling reason to. All we need is the `DW_AT_name` and the `DW_AT_type` that the typedef refers to.

One compelling reason to support `DW_TAG_template_alias` is that with `-gsimple-template-names`, `DW_TAG_typedef`s for alias templates  have their template parameters stripped from the `DW_AT_name`. With just a plain `DW_TAG_typedef`, LLDB has no way to reconstruct the full `DW_AT_name`. But since `DW_TAG_template_alias` can carry template parameter children, LLDB can reconstitute the name by concatenating the `DW_AT_name`s of the child tags.
Michael137 added a commit to Michael137/llvm-project that referenced this pull request Dec 1, 2025
…_TAG_typedef

Depends on:
* llvm#170132

Clang gained the `-gtemplate-alias` not too long ago, which emits C++ alias templates as `DW_TAG_template_alias` (instead of `DW_TAG_typedef`). The main difference is that `DW_TAG_template_alias` has `DW_TAG_template_XXX` children. The flag was not enabled by default because consumers (mainly LLDB) didn't know how to handle it. This patch adds rudimentary support for debugging with `DW_TAG_template_alias`.

This patch simply creates the same kind of `TypedefDecl` as we do for `DW_TAG_typedef`. The more complete solution would be to create a `TypeAliasTemplateDecl` and associated `TypeAliasDecl`. But that would require DWARF to carry generic template information, but currently each `DW_TAG_template_alias` represents a concrete instantiation. We could probably hack up some working AST representation that includes the template parameters, but I currently don't see a compelling reason to. All we need is the `DW_AT_name` and the `DW_AT_type` that the typedef refers to.

One compelling reason to support `DW_TAG_template_alias` is that with `-gsimple-template-names`, `DW_TAG_typedef`s for alias templates  have their template parameters stripped from the `DW_AT_name`. With just a plain `DW_TAG_typedef`, LLDB has no way to reconstruct the full `DW_AT_name`. But since `DW_TAG_template_alias` can carry template parameter children, LLDB can reconstitute the name by concatenating the `DW_AT_name`s of the child tags.
@Michael137 Michael137 force-pushed the lldb/dwarf-tests-helper branch from d8a151f to ac6659b Compare December 2, 2025 06:55
Michael137 added a commit to Michael137/llvm-project that referenced this pull request Dec 2, 2025
…_TAG_typedef

Depends on:
* llvm#170132

Clang gained the `-gtemplate-alias` not too long ago, which emits C++ alias templates as `DW_TAG_template_alias` (instead of `DW_TAG_typedef`). The main difference is that `DW_TAG_template_alias` has `DW_TAG_template_XXX` children. The flag was not enabled by default because consumers (mainly LLDB) didn't know how to handle it. This patch adds rudimentary support for debugging with `DW_TAG_template_alias`.

This patch simply creates the same kind of `TypedefDecl` as we do for `DW_TAG_typedef`. The more complete solution would be to create a `TypeAliasTemplateDecl` and associated `TypeAliasDecl`. But that would require DWARF to carry generic template information, but currently each `DW_TAG_template_alias` represents a concrete instantiation. We could probably hack up some working AST representation that includes the template parameters, but I currently don't see a compelling reason to. All we need is the `DW_AT_name` and the `DW_AT_type` that the typedef refers to.

One compelling reason to support `DW_TAG_template_alias` is that with `-gsimple-template-names`, `DW_TAG_typedef`s for alias templates  have their template parameters stripped from the `DW_AT_name`. With just a plain `DW_TAG_typedef`, LLDB has no way to reconstruct the full `DW_AT_name`. But since `DW_TAG_template_alias` can carry template parameter children, LLDB can reconstitute the name by concatenating the `DW_AT_name`s of the child tags.

assert(llvm::isa_and_nonnull<DWARFASTParserClang>(parser));

return *llvm::dyn_cast<DWARFASTParserClang>(parser);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this just be a non-dynamic cast<>?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup!

… structure

Depends on:
* llvm#170249

We keep repeating the boilerplate of creating a `DWARFASTParserClangStub` and `TypeSystemClangHolder` in all the unit-test cases. Lets extract this into a helper to make the tests easier to grok.
@Michael137 Michael137 force-pushed the lldb/dwarf-tests-helper branch from be0a7bb to 968acbd Compare December 3, 2025 00:52
@Michael137 Michael137 enabled auto-merge (squash) December 3, 2025 00:53
@Michael137 Michael137 merged commit 7685e1f into llvm:main Dec 3, 2025
8 of 9 checks passed
Michael137 added a commit to Michael137/llvm-project that referenced this pull request Dec 3, 2025
…_TAG_typedef

Depends on:
* llvm#170132

Clang gained the `-gtemplate-alias` not too long ago, which emits C++ alias templates as `DW_TAG_template_alias` (instead of `DW_TAG_typedef`). The main difference is that `DW_TAG_template_alias` has `DW_TAG_template_XXX` children. The flag was not enabled by default because consumers (mainly LLDB) didn't know how to handle it. This patch adds rudimentary support for debugging with `DW_TAG_template_alias`.

This patch simply creates the same kind of `TypedefDecl` as we do for `DW_TAG_typedef`. The more complete solution would be to create a `TypeAliasTemplateDecl` and associated `TypeAliasDecl`. But that would require DWARF to carry generic template information, but currently each `DW_TAG_template_alias` represents a concrete instantiation. We could probably hack up some working AST representation that includes the template parameters, but I currently don't see a compelling reason to. All we need is the `DW_AT_name` and the `DW_AT_type` that the typedef refers to.

One compelling reason to support `DW_TAG_template_alias` is that with `-gsimple-template-names`, `DW_TAG_typedef`s for alias templates  have their template parameters stripped from the `DW_AT_name`. With just a plain `DW_TAG_typedef`, LLDB has no way to reconstruct the full `DW_AT_name`. But since `DW_TAG_template_alias` can carry template parameter children, LLDB can reconstitute the name by concatenating the `DW_AT_name`s of the child tags.
@Michael137 Michael137 deleted the lldb/dwarf-tests-helper branch December 3, 2025 02:01
Michael137 added a commit that referenced this pull request Dec 3, 2025
…_TAG_typedef (#170135)

Depends on:
* #170132

Clang gained the `-gtemplate-alias` not too long ago, which emits C++
alias templates as `DW_TAG_template_alias` (instead of
`DW_TAG_typedef`). The main difference is that `DW_TAG_template_alias`
has `DW_TAG_template_XXX` children. The flag was not enabled by default
because consumers (mainly LLDB) didn't know how to handle it. This patch
adds rudimentary support for debugging with `DW_TAG_template_alias`.

This patch simply creates the same kind of `TypedefDecl` as we do for
`DW_TAG_typedef`. The more complete solution would be to create a
`TypeAliasTemplateDecl` and associated `TypeAliasDecl`. But that would
require DWARF to carry generic template information, but currently each
`DW_TAG_template_alias` represents a concrete instantiation. We could
probably hack up some working AST representation that includes the
template parameters, but I currently don't see a compelling reason to.
All we need is the `DW_AT_name` and the `DW_AT_type` that the typedef
refers to.

rdar://137499401
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Dec 3, 2025
…ke we do DW_TAG_typedef (#170135)

Depends on:
* llvm/llvm-project#170132

Clang gained the `-gtemplate-alias` not too long ago, which emits C++
alias templates as `DW_TAG_template_alias` (instead of
`DW_TAG_typedef`). The main difference is that `DW_TAG_template_alias`
has `DW_TAG_template_XXX` children. The flag was not enabled by default
because consumers (mainly LLDB) didn't know how to handle it. This patch
adds rudimentary support for debugging with `DW_TAG_template_alias`.

This patch simply creates the same kind of `TypedefDecl` as we do for
`DW_TAG_typedef`. The more complete solution would be to create a
`TypeAliasTemplateDecl` and associated `TypeAliasDecl`. But that would
require DWARF to carry generic template information, but currently each
`DW_TAG_template_alias` represents a concrete instantiation. We could
probably hack up some working AST representation that includes the
template parameters, but I currently don't see a compelling reason to.
All we need is the `DW_AT_name` and the `DW_AT_type` that the typedef
refers to.

rdar://137499401
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants