Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -666,8 +666,7 @@ // Blocks have a __FuncPtr inside them which is a pointer to a // function of the proper type. - for (DWARFDIE child_die = target_die.GetFirstChild(); - child_die.IsValid(); child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : target_die.children()) { if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""), "__FuncPtr")) { DWARFDIE function_pointer_type = @@ -1826,8 +1825,7 @@ case DW_TAG_GNU_template_parameter_pack: { template_param_infos.packed_args = std::make_unique(); - for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); - child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : die.children()) { if (!ParseTemplateDIE(child_die, *template_param_infos.packed_args)) return false; } @@ -1932,8 +1930,7 @@ if (!parent_die) return false; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { const dw_tag_t tag = die.Tag(); switch (tag) { @@ -2135,8 +2132,7 @@ for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx); it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx; it = m_decl_ctx_to_die.erase(it)) - for (DWARFDIE decl = it->second.GetFirstChild(); decl; - decl = decl.GetSibling()) + for (DWARFDIE decl : it->second.children()) GetClangDeclForDIE(decl); } @@ -2172,8 +2168,7 @@ size_t enumerators_added = 0; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { const dw_tag_t tag = die.Tag(); if (tag == DW_TAG_enumerator) { DWARFAttributes attributes; @@ -2781,8 +2776,7 @@ if (ast == nullptr) return false; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { dw_tag_t tag = die.Tag(); switch (tag) { @@ -2931,8 +2925,7 @@ return 0; size_t arg_idx = 0; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { const dw_tag_t tag = die.Tag(); switch (tag) { case DW_TAG_formal_parameter: { @@ -3051,8 +3044,7 @@ if (!parent_die) return llvm::None; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { const dw_tag_t tag = die.Tag(); if (tag != DW_TAG_subrange_type) continue; @@ -3354,8 +3346,7 @@ } static DWARFDIE FindAnyChildWithAbstractOrigin(const DWARFDIE &context) { - for (DWARFDIE candidate = context.GetFirstChild(); candidate.IsValid(); - candidate = candidate.GetSibling()) { + for (DWARFDIE candidate : context.children()) { if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) { return candidate; } @@ -3519,8 +3510,7 @@ UniqueCStringMap dst_name_to_die; UniqueCStringMap src_name_to_die_artificial; UniqueCStringMap dst_name_to_die_artificial; - for (src_die = src_class_die.GetFirstChild(); src_die.IsValid(); - src_die = src_die.GetSibling()) { + for (DWARFDIE src_die : src_class_die.children()) { if (src_die.Tag() == DW_TAG_subprogram) { // Make sure this is a declaration and not a concrete instance by looking // for DW_AT_declaration set to 1. Sometimes concrete function instances @@ -3538,8 +3528,7 @@ } } } - for (dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid(); - dst_die = dst_die.GetSibling()) { + for (DWARFDIE dst_die : dst_class_die.children()) { if (dst_die.Tag() == DW_TAG_subprogram) { // Make sure this is a declaration and not a concrete instance by looking // for DW_AT_declaration set to 1. Sometimes concrete function instances Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -11,9 +11,11 @@ #include "DWARFBaseDIE.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/iterator_range.h" class DWARFDIE : public DWARFBaseDIE { public: + class child_iterator; using DWARFBaseDIE::DWARFBaseDIE; // Tests @@ -88,6 +90,47 @@ int &decl_line, int &decl_column, int &call_file, int &call_line, int &call_column, lldb_private::DWARFExpression *frame_base) const; + /// The range of all the children of this DIE. + /// + /// This is a template just because child_iterator is not completely defined + /// at this point. + template + llvm::iterator_range children() const { + return llvm::make_range(T(*this), T()); + } +}; + +class DWARFDIE::child_iterator + : public llvm::iterator_facade_base { + /// The current child or an invalid DWARFDie. + DWARFDIE m_die; + +public: + child_iterator() = default; + child_iterator(const DWARFDIE &parent) : m_die(parent.GetFirstChild()) {} + bool operator==(const child_iterator &it) const { + // DWARFDIE's operator== differentiates between an invalid DWARFDIE that + // has a CU but no DIE and one that has neither CU nor DIE. The 'end' + // iterator could be default constructed, so explicitly allow + // (CU, (DIE)nullptr) == (nullptr, nullptr) -> true + if (!m_die.IsValid() && !it.m_die.IsValid()) + return true; + return m_die == it.m_die; + } + const DWARFDIE &operator*() const { + assert(m_die.IsValid() && "Derefencing invalid iterator?"); + return m_die; + } + DWARFDIE &operator*() { + assert(m_die.IsValid() && "Derefencing invalid iterator?"); + return m_die; + } + child_iterator &operator++() { + assert(m_die.IsValid() && "Incrementing invalid iterator?"); + m_die = m_die.GetSibling(); + return *this; + } }; #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDIE_H Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -192,7 +192,7 @@ } if (check_children) { - for (DWARFDIE child = GetFirstChild(); child; child = child.GetSibling()) { + for (DWARFDIE child : children()) { if (DWARFDIE child_result = child.LookupDeepestBlock(address)) return child_result; } Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -360,8 +360,7 @@ } } - for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); - child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : die.children()) { GetTypes(child_die, min_die_offset, max_die_offset, type_mask, type_set); } } @@ -985,8 +984,7 @@ if (!die) return false; - for (DWARFDIE child_die = die.GetFirstChild(); child_die; - child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : die.children()) { if (child_die.Tag() != DW_TAG_imported_declaration) continue; @@ -1245,8 +1243,7 @@ bool SymbolFileDWARF::ClassOrStructIsVirtual(const DWARFDIE &parent_die) { if (parent_die) { - for (DWARFDIE die = parent_die.GetFirstChild(); die; - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { dw_tag_t tag = die.Tag(); bool check_virtuality = false; switch (tag) { @@ -3419,8 +3416,7 @@ // Give the concrete function die specified by "func_die_offset", find the // concrete block whose DW_AT_specification or DW_AT_abstract_origin points // to "spec_block_die_offset" - for (DWARFDIE child_die = die.GetFirstChild(); child_die; - child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : die.children()) { DWARFDIE result_die = FindBlockContainingSpecification(child_die, spec_block_die_offset); if (result_die) @@ -3549,8 +3545,7 @@ static CallSiteParameterArray CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { CallSiteParameterArray parameters; - for (DWARFDIE child = call_site_die.GetFirstChild(); child.IsValid(); - child = child.GetSibling()) { + for (DWARFDIE child : call_site_die.children()) { if (child.Tag() != DW_TAG_call_site_parameter && child.Tag() != DW_TAG_GNU_call_site_parameter) continue; @@ -3615,8 +3610,7 @@ // For now, assume that all entries are nested directly under the subprogram // (this is the kind of DWARF LLVM produces) and parse them eagerly. std::vector> call_edges; - for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid(); - child = child.GetSibling()) { + for (DWARFDIE child : function_die.children()) { if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site) continue;