Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -275,7 +275,13 @@ iterator begin() const; iterator end() const; + iterator_range children() const; + + class reverse_iterator; + + reverse_iterator rbegin() const; + reverse_iterator rend() const; }; class DWARFDie::attribute_iterator : @@ -320,28 +326,24 @@ } class DWARFDie::iterator - : public iterator_facade_base { DWARFDie Die; + public: iterator() = default; - explicit iterator(DWARFDie D) : Die(D) { - } + explicit iterator(DWARFDie D) : Die(D) {} iterator &operator++() { Die = Die.getSibling(); return *this; } - iterator &operator--() { - Die = Die.getPreviousSibling(); - return *this; - } - 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 @@ -358,6 +360,37 @@ return make_range(begin(), end()); } +class DWARFDie::reverse_iterator + : public iterator_facade_base { + DWARFDie Die; + +public: + reverse_iterator() = default; + + explicit reverse_iterator(DWARFDie D) : Die(D.getPreviousSibling()) {} + + reverse_iterator &operator++() { + Die = Die.getPreviousSibling(); + 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; } + bool operator!=(const reverse_iterator &X) const { return Die != X.Die; } +}; + +// These inline functions must follow the DWARFDie::reverse_iterator definition +// above as they use functions from that class. +inline DWARFDie::reverse_iterator DWARFDie::rbegin() const { + return reverse_iterator(getLastChild()); +} + +inline DWARFDie::reverse_iterator DWARFDie::rend() const { + return reverse_iterator(getFirstChild()); +} + } // 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,42 @@ 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. + size_t Idx = 0; + for (auto Child : A) { + switch (Idx) { + case 0: + EXPECT_EQ(Child, B); + break; + case 1: + EXPECT_EQ(Child, C); + break; + case 2: + EXPECT_EQ(Child, D); + break; + default: + break; + } + Idx++; + } + + Idx = 0; + for (auto Child : llvm::make_range(A.rbegin(), A.rend())) { + switch (Idx) { + case 0: + EXPECT_EQ(Child, D); + break; + case 1: + EXPECT_EQ(Child, C); + break; + case 2: + EXPECT_EQ(Child, B); + break; + default: + break; + } + Idx++; + } } TEST(DWARFDebugInfo, TestDWARFDie) {