Move ElaboratingDIEIterator into implementation file.

This is not used outside of the private implementation of the class,
so hiding in the implementation file is a nice way of simplifying
the external interface.

Differential Revision: https://reviews.llvm.org/D59164

llvm-svn: 355973
This commit is contained in:
Zachary Turner 2019-03-12 20:50:29 +00:00
parent 0c29402eb4
commit d5364dfa6d
2 changed files with 66 additions and 69 deletions

View File

@ -17,20 +17,75 @@
using namespace lldb_private;
void DWARFDIE::ElaboratingDIEIterator::Next() {
assert(!m_worklist.empty() && "Incrementing end iterator?");
namespace {
// Pop the current item from the list.
DWARFDIE die = m_worklist.back();
m_worklist.pop_back();
/// Iterate through all DIEs elaborating (i.e. reachable by a chain of
/// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For
/// convenience, the starting die is included in the sequence as the first
/// item.
class ElaboratingDIEIterator
: public std::iterator<std::input_iterator_tag, DWARFDIE> {
// And add back any items that elaborate it.
for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) {
if (DWARFDIE d = die.GetReferencedDIE(attr))
if (m_seen.insert(die.GetID()).second)
m_worklist.push_back(d);
// The operating invariant is: top of m_worklist contains the "current" item
// and the rest of the list are items yet to be visited. An empty worklist
// means we've reached the end.
// Infinite recursion is prevented by maintaining a list of seen DIEs.
// Container sizes are optimized for the case of following DW_AT_specification
// and DW_AT_abstract_origin just once.
llvm::SmallVector<DWARFDIE, 2> m_worklist;
llvm::SmallSet<lldb::user_id_t, 3> m_seen;
void Next() {
assert(!m_worklist.empty() && "Incrementing end iterator?");
// Pop the current item from the list.
DWARFDIE die = m_worklist.back();
m_worklist.pop_back();
// And add back any items that elaborate it.
for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) {
if (DWARFDIE d = die.GetReferencedDIE(attr))
if (m_seen.insert(die.GetID()).second)
m_worklist.push_back(d);
}
}
public:
/// An iterator starting at die d.
explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {}
/// End marker
ElaboratingDIEIterator() {}
const DWARFDIE &operator*() const { return m_worklist.back(); }
ElaboratingDIEIterator &operator++() {
Next();
return *this;
}
ElaboratingDIEIterator operator++(int) {
ElaboratingDIEIterator I = *this;
Next();
return I;
}
friend bool operator==(const ElaboratingDIEIterator &a,
const ElaboratingDIEIterator &b) {
if (a.m_worklist.empty() || b.m_worklist.empty())
return a.m_worklist.empty() == b.m_worklist.empty();
return a.m_worklist.back() == b.m_worklist.back();
}
friend bool operator!=(const ElaboratingDIEIterator &a,
const ElaboratingDIEIterator &b) {
return !(a == b);
}
};
llvm::iterator_range<ElaboratingDIEIterator>
elaborating_dies(const DWARFDIE &die) {
return llvm::make_range(ElaboratingDIEIterator(die),
ElaboratingDIEIterator());
}
} // namespace
DWARFDIE
DWARFDIE::GetParent() const {
@ -229,7 +284,7 @@ bool DWARFDIE::IsStructUnionOrClass() const {
}
bool DWARFDIE::IsMethod() const {
for (DWARFDIE d: elaborating_dies())
for (DWARFDIE d : elaborating_dies(*this))
if (d.GetParent().IsStructUnionOrClass())
return true;
return false;

View File

@ -14,8 +14,6 @@
class DWARFDIE : public DWARFBaseDIE {
public:
class ElaboratingDIEIterator;
using DWARFBaseDIE::DWARFBaseDIE;
//----------------------------------------------------------------------
@ -33,8 +31,6 @@ public:
DWARFDIE
GetContainingDWOModuleDIE() const;
inline llvm::iterator_range<ElaboratingDIEIterator> elaborating_dies() const;
//----------------------------------------------------------------------
// Accessing information about a DIE
//----------------------------------------------------------------------
@ -121,58 +117,4 @@ public:
lldb_private::CompilerDeclContext GetContainingDeclContext() const;
};
/// Iterate through all DIEs elaborating (i.e. reachable by a chain of
/// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For
/// convenience, the starting die is included in the sequence as the first
/// item.
class DWARFDIE::ElaboratingDIEIterator
: public std::iterator<std::input_iterator_tag, DWARFDIE> {
// The operating invariant is: top of m_worklist contains the "current" item
// and the rest of the list are items yet to be visited. An empty worklist
// means we've reached the end.
// Infinite recursion is prevented by maintaining a list of seen DIEs.
// Container sizes are optimized for the case of following DW_AT_specification
// and DW_AT_abstract_origin just once.
llvm::SmallVector<DWARFDIE, 2> m_worklist;
llvm::SmallSet<lldb::user_id_t, 3> m_seen;
void Next();
public:
/// An iterator starting at die d.
explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {}
/// End marker
ElaboratingDIEIterator() {}
const DWARFDIE &operator*() const { return m_worklist.back(); }
ElaboratingDIEIterator &operator++() {
Next();
return *this;
}
ElaboratingDIEIterator operator++(int) {
ElaboratingDIEIterator I = *this;
Next();
return I;
}
friend bool operator==(const ElaboratingDIEIterator &a,
const ElaboratingDIEIterator &b) {
if (a.m_worklist.empty() || b.m_worklist.empty())
return a.m_worklist.empty() == b.m_worklist.empty();
return a.m_worklist.back() == b.m_worklist.back();
}
friend bool operator!=(const ElaboratingDIEIterator &a,
const ElaboratingDIEIterator &b) {
return !(a == b);
}
};
llvm::iterator_range<DWARFDIE::ElaboratingDIEIterator>
DWARFDIE::elaborating_dies() const {
return llvm::make_range(ElaboratingDIEIterator(*this),
ElaboratingDIEIterator());
}
#endif // SymbolFileDWARF_DWARFDIE_h_