teemperor created this revision.
teemperor added a reviewer: LLDB.
teemperor added a project: LLDB.
Herald added a subscriber: JDevlieghere.
Herald added a reviewer: shafik.
teemperor requested review of this revision.
This patch adds the ability to get a DWARFDIE's children as an LLVM range.
This way we can use for range loops to iterate over them and we can use
LLVM's algorithms like `llvm::all_of` to query all children.
The implementation has to do some small shenanigans as the iterator
needs to store a DWARFDIE, but a DWARFDIE container is also a DWARFDIE
so it can't return the iterator by value. I just made the `children` getter a
templated function to avoid the cyclic dependency.
https://reviews.llvm.org/D103172
Files:
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
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<std::unique_ptr<CallEdge>> 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;
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 <typename T = child_iterator>
+ llvm::iterator_range<T> children() const {
+ return llvm::make_range(T(*this), T());
+ }
+};
+
+class DWARFDIE::child_iterator
+ : public llvm::iterator_facade_base<DWARFDIE::child_iterator,
+ std::forward_iterator_tag, DWARFDIE> {
+ /// 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/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<TypeSystemClang::TemplateParameterInfos>();
- 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<DWARFDIE> dst_name_to_die;
UniqueCStringMap<DWARFDIE> src_name_to_die_artificial;
UniqueCStringMap<DWARFDIE> 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
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits