Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -275,12 +275,16 @@ iterator begin() const; iterator end() const; + + std::reverse_iterator rbegin() const; + std::reverse_iterator rend() const; + iterator_range children() const; }; -class DWARFDie::attribute_iterator : - public iterator_facade_base { +class DWARFDie::attribute_iterator + : public iterator_facade_base { /// The DWARF DIE we are extracting attributes from. DWARFDie Die; /// The value vended to clients via the operator*() or operator->(). @@ -303,12 +307,14 @@ attribute_iterator &operator--(); explicit operator bool() const { return AttrValue.isValid(); } const DWARFAttribute &operator*() const { return AttrValue; } - bool operator==(const attribute_iterator &X) const { return Index == X.Index; } + bool operator==(const attribute_iterator &X) const { + return Index == X.Index; + } }; inline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) { return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() && - LHS.getDwarfUnit() == RHS.getDwarfUnit(); + LHS.getDwarfUnit() == RHS.getDwarfUnit(); } inline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) { @@ -323,11 +329,13 @@ : public iterator_facade_base { DWARFDie Die; + + friend std::reverse_iterator; + public: iterator() = default; - explicit iterator(DWARFDie D) : Die(D) { - } + explicit iterator(DWARFDie D) : Die(D) {} iterator &operator++() { Die = Die.getSibling(); @@ -342,6 +350,7 @@ explicit operator bool() const { return Die.isValid(); } const DWARFDie &operator*() const { return Die; } bool operator==(const iterator &X) const { return Die == X.Die; } + bool operator!=(const iterator &X) const { return Die != X.Die; } }; // These inline functions must follow the DWARFDie::iterator definition above @@ -360,4 +369,73 @@ } // end namespace llvm +namespace std { +using namespace llvm; +template <> +class reverse_iterator + : public iterator< + typename iterator_traits::iterator_category, + typename iterator_traits::value_type, + typename iterator_traits::difference_type, + typename iterator_traits::pointer, + typename iterator_traits::reference> { + +private: + DWARFDie Die; + bool AtEnd; + +public: + typedef DWARFDie::iterator iterator_type; + typedef typename iterator_traits::difference_type + difference_type; + typedef typename iterator_traits::reference reference; + typedef typename iterator_traits::pointer pointer; + + reverse_iterator(DWARFDie::iterator It) + : Die(It.Die), AtEnd(!It.Die.getPreviousSibling()) { + if (!AtEnd) + Die = Die.getPreviousSibling(); + } + + reverse_iterator &operator++() { + assert(!AtEnd && "Incrementing rend"); + DWARFDie D = Die.getPreviousSibling(); + if (D) + Die = D; + else + AtEnd = true; + return *this; + } + + reverse_iterator &operator--() { + if (AtEnd) { + AtEnd = false; + return *this; + } + Die = Die.getSibling(); + assert(!Die.isNULL() && "Decrementing rbegin"); + return *this; + } + + explicit operator bool() const { return Die.isValid(); } + const DWARFDie &operator*() const { return Die; } + bool operator==(const reverse_iterator &X) const { + return Die == X.Die && AtEnd == X.AtEnd; + } + + bool operator!=(const reverse_iterator &X) const { + return !(*this == X); + } +}; +} // namespace std + +namespace llvm { +inline std::reverse_iterator DWARFDie::rbegin() const { + return make_reverse_iterator(end()); +} + +inline std::reverse_iterator DWARFDie::rend() const { + return make_reverse_iterator(begin()); +} +} // end namespace llvm #endif // LLVM_DEBUGINFO_DWARFDIE_H Index: llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp =================================================================== --- llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -1078,26 +1078,11 @@ EXPECT_EQ(C1.getParent(), C); EXPECT_EQ(C2.getParent(), C); - // Make sure bidirectional iterator works as expected. - auto Begin = A.begin(); - auto End = A.end(); - auto It = A.begin(); - - EXPECT_EQ(It, Begin); - EXPECT_EQ(*It, B); - ++It; - EXPECT_EQ(*It, C); - ++It; - EXPECT_EQ(*It, D); - ++It; - EXPECT_EQ(It, End); - --It; - EXPECT_EQ(*It, D); - --It; - EXPECT_EQ(*It, C); - --It; - EXPECT_EQ(*It, B); - EXPECT_EQ(It, Begin); + // Make sure iterators work as expected. + EXPECT_THAT(std::vector(A.begin(), A.end()), + testing::ElementsAre(B, C, D)); + EXPECT_THAT(std::vector(A.rbegin(), A.rend()), + testing::ElementsAre(D, C, B)); } TEST(DWARFDebugInfo, TestDWARFDie) {