Skip to content

Conversation

tgs-sc
Copy link
Contributor

@tgs-sc tgs-sc commented Aug 18, 2025

[lldb][DWARFASTParserClang] Added a check for the specialization existence

While debugging an application with incorrect dwarf information, where
DW_TAG_template_value_parameter was lost, I found that lldb does not
check that the corresponding specialization exists. As a result, at the
stage when ASTImporter works, the type is completed in such a way that
it inherits from itself. And during the calculation of layout, an
infinite recursion occurs. To catch this error, I added a corresponding check
at the stage of restoring the type from dwarf information. I also added a
trivial assert in clang to check that the class does not inherit from itself.

@tgs-sc tgs-sc requested a review from JDevlieghere as a code owner August 18, 2025 14:31
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added clang Clang issues not falling into any other category lldb clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Aug 18, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 18, 2025

@llvm/pr-subscribers-lldb

@llvm/pr-subscribers-clang

Author: None (tgs-sc)

Changes
[lldb][DWARFASTParserClang] Added a check for the specialization existence

While debugging an application with incorrect dwarf information, where
DW_TAG_template_value_parameter was lost, I found that lldb does not
check that the corresponding specialization exists. As a result, at the
stage when ASTImporter works, the type is completed in such a way that
it inherits from itself. And during the calculation of layout, an
infinite recursion occurs. To catch this error, I added a corresponding check
at the stage of restoring the type from dwarf information. I also added a
trivial assert in clang to check that the class does not inherit from itself.

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

2 Files Affected:

  • (modified) clang/lib/AST/RecordLayoutBuilder.cpp (+2)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (+16)
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 6d819031cbef4..93571543f1c7d 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -187,6 +187,8 @@ void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
   // Check the bases.
   for (const CXXBaseSpecifier &Base : Class->bases()) {
     const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
+    // Assert to prevent infinite recursion.
+    assert(BaseDecl != Class && "Class cannot inherit from itself.");
 
     CharUnits EmptySize;
     const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index c76d67b47b336..6643751cd237a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -1873,6 +1873,22 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
     clang_type =
         m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);
 
+    // Try to find an existing specialization with these template arguments and
+    // template parameter list.
+    void *InsertPos = nullptr;
+    if (!class_template_decl->findSpecialization(template_param_infos.GetArgs(),
+                                                 InsertPos))
+      // Add this specialization to the class template.
+      class_template_decl->AddSpecialization(class_specialization_decl,
+                                             InsertPos);
+    else {
+      dwarf->GetObjectFile()->GetModule()->ReportError(
+          "SymbolFileDWARF({0:p}) - Specialization for "
+          "clang::ClassTemplateDecl({1:p}) already exists.",
+          static_cast<void *>(this), static_cast<void *>(class_template_decl));
+      return TypeSP();
+    }
+
     m_ast.SetMetadata(class_template_decl, metadata);
     m_ast.SetMetadata(class_specialization_decl, metadata);
   }

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from 25d756b to 835700e Compare August 18, 2025 14:32
@Michael137
Copy link
Member

Hmm yea guarding against incorrect DWARF has been mostly best effort. Can you provide a test-case for this?

@Michael137
Copy link
Member

Michael137 commented Aug 18, 2025

Also, please split out the clang change into a separate PR. The clang maintainers can comment there on whether that's a useful thing to have in place

@tgs-sc
Copy link
Contributor Author

tgs-sc commented Aug 18, 2025

Hmm yea guarding against incorrect DWARF has been mostly best effort. Can you provide a test-case for this?

Sure. Originally this bug was discovered by debugging llc, but I minimized it to such example:

--- b1.cc ---

#include <optional>
#include <iostream>

struct Type {
  Type() {
    printf("ctor\n");
  }

  Type(const Type& T) {
    printf("ctor copy\n");
  }

  Type(Type&& ) {
    printf("ctor move\n");
  }

  ~Type() {
    printf("dtor");
  }
};

std::optional<Type> var{};
std::optional<Type>* x = &var;

--- b2.cc ---

#include <iostream>

class Type;
namespace std{
template<typename T>
class optional;
}
extern std::optional<Type>* x;

int main() {
        std::cout << x << std::endl;
}

Compilation: /usr/bin/g++ b1.cc b2.cc -g -O0 -std=c++17 -o b.out. The version of g++ should be 9.4.0.
Running: lldb b.out -o "b main" -o "r" -o "p x"
The problem is going to happen in internals of std::optional (https://gcc.gnu.org/onlinedocs/gcc-12.3.0/libstdc++/api/a00152_source.html) as it has 2 specializations of _Optional_payload that have the same type and differ only with template parameters.

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from 835700e to f19ba13 Compare August 18, 2025 15:03
@tgs-sc
Copy link
Contributor Author

tgs-sc commented Aug 18, 2025

Also, please split out the clang change into a separate PR. The clang maintainers can comment there on whether that's a useful thing to have in place

Addressed. I made a PR (#154134) to clang with adding assert as seeing backtrace with 16k functions is not very nice.

@tgs-sc tgs-sc changed the title [clang][AST] Added assert to prevent infinite recursion in computing layout [lldb][DWARFASTParserClang] Added a check for the specialization existence Aug 18, 2025
@tgs-sc
Copy link
Contributor Author

tgs-sc commented Aug 19, 2025

@Michael137, is it OK?

@tgs-sc
Copy link
Contributor Author

tgs-sc commented Aug 26, 2025

@JDevlieghere, can you also please look at this?

@tgs-sc
Copy link
Contributor Author

tgs-sc commented Aug 27, 2025

This is a reproduction in godbolt: https://godbolt.org/z/aKWETszEY.

@Michael137
Copy link
Member

This is a reproduction in godbolt: https://godbolt.org/z/r96v6cKEs.

Thanks, we will somehow need to turn this into a test. I'll have a more detailed look later in the week

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from f19ba13 to 5272b4f Compare September 5, 2025 15:34
@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 5, 2025

@Michael137, can you please take a look as a week has passed? I added unittest and updated godbolt reproduction.

Copy link

github-actions bot commented Sep 7, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch 2 times, most recently from 5a639e6 to f86f3ac Compare September 7, 2025 19:12
@Michael137
Copy link
Member

Michael137 commented Sep 8, 2025

Sorry for the delay. Thanks for adding the test. That was really helpful

This is the DWARF of the test yaml:

test.o: file format elf64-x86-64

.debug_info contents:
0x00000000: Compile Unit: length = 0x0000009e, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x000000a2)

0x0000000b: DW_TAG_compile_unit
              DW_AT_producer    ("GNU C++14 9.4.0 -mtune=generic -march=x86-64 -g -O0 -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection")
              DW_AT_language    (DW_LANG_C_plus_plus)
              DW_AT_name        ("maic.cc")
              DW_AT_comp_dir    ("/root/os-llvm/llvm-project")
              DW_AT_low_pc      (0x0000000000001129)
              DW_AT_high_pc     (0x0000000000001138)
              DW_AT_stmt_list   (0x00000000)

0x0000002d:   DW_TAG_structure_type
                DW_AT_name      ("Type")
                DW_AT_byte_size (0x01)
                DW_AT_decl_file ("/root/os-llvm/llvm-project/maic.cc")
                DW_AT_decl_line (1)
                DW_AT_decl_column       (8)

0x00000036:   DW_TAG_structure_type
                DW_AT_name      ("_Optional_payload<Type, true, false, false>")
                DW_AT_byte_size (0x01)
                DW_AT_decl_file ("/root/os-llvm/llvm-project/maic.cc")
                DW_AT_decl_line (5)
                DW_AT_decl_column       (32)
                DW_AT_sibling   (0x0000004d)

0x00000043:     DW_TAG_template_type_parameter
                  DW_AT_name    ("_Tp")
                  DW_AT_type    (0x0000002d "Type")

0x0000004c:     NULL

0x0000004d:   DW_TAG_structure_type
                DW_AT_name      ("_Optional_payload<Type, false, false, true>")
                DW_AT_byte_size (0x01)
                DW_AT_decl_file ("/root/os-llvm/llvm-project/maic.cc")
                DW_AT_decl_line (8)
                DW_AT_decl_column       (8)
                DW_AT_sibling   (0x0000006a)

0x0000005a:     DW_TAG_inheritance
                  DW_AT_type    (0x00000036 "_Optional_payload<Type, true, false, false>")
                  DW_AT_data_member_location    (0x00)

0x00000060:     DW_TAG_template_type_parameter
                  DW_AT_name    ("_Tp")
                  DW_AT_type    (0x0000002d "Type")

0x00000069:     NULL

So basically we have a _Optional_payload specialization that inherits from a different _Optional_payload specialization. LLDB creates two different ClassTemplateSpecializationDecls for these, but because the two specializations are missing the DW_TAG_template_value_parameters, in the final AST, the ASTImporter thinks they are the same. So it ends up making a decl that inherits from itself, as you mention in the PR description. Presumably this happens because they structurally match, and the ASTImporter re-uses one of the previously imported specialization decl. Your patch makes our AST construction less brittle (and this is also what Clang and the ASTImporter do). So generally this LGTM

@@ -1725,6 +1725,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
const dw_tag_t tag = die.Tag();
SymbolFileDWARF *dwarf = die.GetDWARF();
LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU());
ModuleSP module_sp = dwarf->GetObjectFile()->GetModule();
Copy link
Member

Choose a reason for hiding this comment

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

Please revert these drive-by changes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

class_template_decl->AddSpecialization(class_specialization_decl,
InsertPos);
else {
module_sp->ReportError("SymbolFileDWARF({0:p}) - Specialization for "
Copy link
Member

@Michael137 Michael137 Sep 8, 2025

Choose a reason for hiding this comment

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

I don't think we should be reporting this to the user console. Particularly, a user wouldn't really be aware of what a Specialization for clang::ClassTemplateDecl is and what the issue is with it already existing.

Lets just LogMessage here for now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed


llvm::SmallVector<lldb::TypeSP, 3> types;
for (DWARFDIE die : cu_die.children()) {
if (die.Tag() == DW_TAG_structure_type) {
Copy link
Member

Choose a reason for hiding this comment

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

How about also checking that:

llvm::StringRef(die.GetName()).starts_with("_Optional_payload")

So you don't parse the struct Type. Then you just assert that one of the types is nullptr and the other isn't. Makes the test a bit clearer

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

@@ -599,6 +599,39 @@ TEST_F(DWARFASTParserClangTests, TestDefaultTemplateParamParsing) {
}
}

TEST_F(DWARFASTParserClangTests, TestSpecDeclExistsError) {
// Tests checking error if ClassTemplateSpecializationDecl already exists.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Tests checking error if ClassTemplateSpecializationDecl already exists.
// Tests that parsing a ClassTemplateSpecializationDecl that already exists
// is handled gracefully.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

# }
#
# YAML generated on Linux using obj2yaml on the above program
# compiled with G++.
Copy link
Member

@Michael137 Michael137 Sep 8, 2025

Choose a reason for hiding this comment

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

Lets add a comment saying this is malformed DWARF that is missing DW_TAG_template_value_parameter entries, which is important for the test because that makes the two specializations look like identical structure definitions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

if (!args.empty() &&
!class_template_decl->findSpecialization(args, InsertPos))
// Add this specialization to the class template.
class_template_decl->AddSpecialization(class_specialization_decl,
InsertPos);
Copy link
Member

Choose a reason for hiding this comment

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

Can we move this into CreateClassTemplateSpecializationDecl? That's where we also setInstantiationOf.

That way we could even test this functionality in TestTypeSystemClang

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am afraid no as if we have already found specialization in this function, we should return nullptr. And as I see this may cause errors.

Copy link
Member

@Michael137 Michael137 Sep 8, 2025

Choose a reason for hiding this comment

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

Not sure I understand. What's preventing us from calling findSpecialization on the newly created decl inside CreateClassTemplateSpecializationDecl?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And what should we do if we found this specialization?

Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't returning a nullptr work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from f076aea to 407331b Compare September 8, 2025 11:55
Copy link
Member

@Michael137 Michael137 left a comment

Choose a reason for hiding this comment

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

LGTM (module remaining comments)

Comment on lines 1880 to 1883
"SymbolFileDWARF({0:p}) - Specialization for "
"clang::ClassTemplateDecl({1:p}) already exists.",
static_cast<void *>(this),
static_cast<void *>(class_template_decl));
Copy link
Member

Choose a reason for hiding this comment

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

I think the casts are not needed:

Suggested change
"SymbolFileDWARF({0:p}) - Specialization for "
"clang::ClassTemplateDecl({1:p}) already exists.",
static_cast<void *>(this),
static_cast<void *>(class_template_decl));
"SymbolFileDWARF({0:p}) - Specialization for "
"clang::ClassTemplateDecl({1}, {2:p}) already exists.",
this, llvm::StringRef(attrs.name), class_template_decl);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

Comment on lines 1680 to 1679
if (!class_template_decl->findSpecialization(args, InsertPos)) {
// Add this specialization to the class template.
class_template_decl->AddSpecialization(class_template_specialization_decl,
InsertPos);
} else
// Specialization exists, so return nullptr.
return nullptr;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (!class_template_decl->findSpecialization(args, InsertPos)) {
// Add this specialization to the class template.
class_template_decl->AddSpecialization(class_template_specialization_decl,
InsertPos);
} else
// Specialization exists, so return nullptr.
return nullptr;
if (class_template_decl->findSpecialization(args, InsertPos))
return nullptr;
class_template_decl->AddSpecialization(class_template_specialization_decl,
InsertPos);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from 407331b to 4c41e84 Compare September 8, 2025 12:08
@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 8, 2025

@Michael137, do you think that this PR(#154134) is still needed?

Comment on lines 1880 to 1881
"SymbolFileDWARF({0:p}) - Specialization for "
"clang::ClassTemplateDecl({1}, {2:p}) already exists.",
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"SymbolFileDWARF({0:p}) - Specialization for "
"clang::ClassTemplateDecl({1}, {2:p}) already exists.",
"SymbolFileDWARF({0:p}) - Failed to create specialization for "
"clang::ClassTemplateDecl({1}, {2:p}).",

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

@@ -1676,6 +1676,13 @@ TypeSystemClang::CreateClassTemplateSpecializationDecl(
class_template_specialization_decl->setInstantiationOf(class_template_decl);
class_template_specialization_decl->setTemplateArgs(
TemplateArgumentList::CreateCopy(ast, args));
// Specialization exists, so return nullptr.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Specialization exists, so return nullptr.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

void *InsertPos = nullptr;
if (class_template_decl->findSpecialization(args, InsertPos))
return nullptr;
// Add this specialization to the class template.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Add this specialization to the class template.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

@@ -1873,6 +1873,17 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
clang_type =
m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);
Copy link
Member

@Michael137 Michael137 Sep 8, 2025

Choose a reason for hiding this comment

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

lets move the new check before we call CreateClassTemplateSpecializationType

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

@Michael137
Copy link
Member

Can you rebase your PR on main and resolve the conflict in TypeSystemClang.cpp?

@Michael137
Copy link
Member

@Michael137, do you think that this PR(#154134) is still needed?

I'll comment on that PR

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from 4c41e84 to 795c01c Compare September 8, 2025 12:24
@Michael137 Michael137 enabled auto-merge (squash) September 8, 2025 12:29
@Michael137
Copy link
Member

Based on the test failure in TestCppTemplateArguments.py maybe we need to return the ClassTemplateDeclSpecialization that we found, instead of returning nullptr. We would create a new TypeSP for it, but that shouldn't be an issue i think

@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 8, 2025

Based on the test failure in TestCppTemplateArguments.py maybe we need to return the
ClassTemplateDeclSpecialization that we found, instead of returning nullptr. We would create a new TypeSP for it, but
that shouldn't be an issue i think

But check to nullptr in DWARFASTParserClang.cpp fails in this case.

@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 8, 2025

@Michael137, probably we should return finding and adding specialization in DWARFASTParserClang.cpp?

auto-merge was automatically disabled September 8, 2025 16:26

Head branch was pushed to by a user without write access

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from 795c01c to cc0df38 Compare September 8, 2025 16:26
@Michael137
Copy link
Member

Michael137 commented Sep 8, 2025

@Michael137, probably we should return finding and adding specialization in DWARFASTParserClang.cpp?

That would be equivalent to the way your current version handles this right? I don't see how that would change anything.

I now realize this is trickier than expected. E.g., the infinite recursion actually reproduces with valid DWARF. Consider:

template <typename T> struct Foo;

template <> struct Foo<__bf16> {};

template <> struct Foo<_Float16> : Foo<__bf16> {};

int main() {
  Foo<_Float16> f1;
  return 0;
}

This will crash:

clang++ main.cpp -g
lldb a.out -o "br se -p return -X main" -o run -o "expr f1"

__bf16 and _Float16 both are floating point types with the same bit-size. I haven't stepped through LLDB in this case but what I suspect is happening is that LLDB pretends they both are __fp16 (via GetBuiltinTypeForEncodingAndBitSize most likely). So we have the same issue as your malformed DWARF case where a template specialization derives from another specialization but in the AST that LLDB creates the base specialization has the same template parameter types as the derived class.

There are some defensive checks against creating duplicate decls which relies on typenames:

// Add our type to the unique type map so we don't end up creating many
// copies of the same type over and over in the ASTContext for our
// module
unique_ast_entry_up->m_type_sp = type_sp;
unique_ast_entry_up->m_die = die;
unique_ast_entry_up->m_declaration = unique_decl;
unique_ast_entry_up->m_byte_size = byte_size;
unique_ast_entry_up->m_is_forward_declaration = attrs.is_forward_declaration;
dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
*unique_ast_entry_up);

However, in my reproducer it doesn't work because, in DWARF, the typenames differ:

                DW_AT_name      ("Foo<_Float16>")
...
                DW_AT_name      ("Foo<__bf16>")

It's just that in the LLDB AST, the template parameter types don't match what we encoded in the structure's name in DWARF.

My first instinct is that we might need to adjust the heuristics of the GetUniqueDWARFASTTypeMap to account for this. But I haven't thought this through enough to know whether this is possible/desirable.

@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 8, 2025

Seems like problem is in GetBuiltinTypeForDWARFEncodingAndBitSize where we ignore type_name for DW_ATE_float. I think that we should take into account type_name there.

Because if we look into the dwarf, it differs only with type_name:

0x00000134:   DW_TAG_base_type
                DW_AT_name	("_Float16")
                DW_AT_encoding	(DW_ATE_float)
                DW_AT_byte_size	(0x02)
...
0x00000158:   DW_TAG_base_type
                DW_AT_name	("__bf16")
                DW_AT_encoding	(DW_ATE_float)
                DW_AT_byte_size	(0x02)

I think the best solution would be to cover this type in this function.

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from cc0df38 to c6a6006 Compare September 9, 2025 09:35
@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 9, 2025

@Michael137, can you please rerun CI in this PR? I guess my fix is gonna work.

@@ -959,6 +959,9 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
if (type_name == "long double" &&
QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
return GetType(ast.LongDoubleTy);
if (type_name == "__bf16" &&
Copy link
Member

Choose a reason for hiding this comment

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

This needs to be a separate PR

Copy link
Member

Choose a reason for hiding this comment

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

Lets also add a case for Float16Ty (i.e., _Float16)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This needs to be a separate PR

OK, I will create one. With a test?

Copy link
Member

Choose a reason for hiding this comment

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

Ideally yes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Don't you think there is an error in the test?

Test:

Foo<_Float16, _Float16(1.0)> temp7;
Foo<__bf16, __bf16(1.0)> temp8;

Check:

        value = self.expect_expr("temp8", result_type="Foo<__fp16, __fp16>")
        self.assertFalse(value.GetType().GetTemplateArgumentValue(target, 1))

Current output:

  AssertionError: 'Foo<__fp16, __fp16>' != 'Foo<__bf16, __bf16>'
  - Foo<__fp16, __fp16>
  ?        -       -
  + Foo<__bf16, __bf16>
  ?       +       +

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a new created PR: #157674

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from c6a6006 to eebd3ce Compare September 10, 2025 13:30
@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from eebd3ce to f158ed3 Compare October 1, 2025 10:49
@tgs-sc
Copy link
Contributor Author

tgs-sc commented Oct 1, 2025

@Michael137, can you please rerun CI to this PR? As #157674 was merged, this one can be merged too I think.

…tence

While debugging an application with incorrect dwarf information, where
DW_TAG_template_value_parameter was lost, I found that lldb does not
check that the corresponding specialization exists. As a result, at the
stage when ASTImporter works, the type is completed in such a way that
it inherits from itself. And during the calculation of layout, an
infinite recursion occurs. To catch this error, I added a corresponding check
at the stage of restoring the type from dwarf information.
@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-infinite-recursion-segfault branch from dec97f1 to 42a5c3d Compare October 3, 2025 21:47
@tgs-sc
Copy link
Contributor Author

tgs-sc commented Oct 3, 2025

I close it as it is actually merged (42a5c3d)

@tgs-sc tgs-sc closed this Oct 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category lldb

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants