Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -319,28 +319,48 @@ return LHS.getOffset() < RHS.getOffset(); } -class DWARFDie::iterator - : public iterator_facade_base { +/// Although this class is called iterator, it's actually not because it's +/// storing a DWARFDie in memory. This means that returning a const ref to it +/// is bogus, as it's invalidated as soon as you modify the "iterator". To +/// prevent this from happening, we have it return the DWARFDie by value. +class DWARFDie::iterator { DWARFDie Die; + public: + using difference_type = std::ptrdiff_t; + using value_type = DWARFDie; + using pointer = value_type; + using reference = value_type; + using iterator_category = std::bidirectional_iterator_tag; + iterator() = default; - explicit iterator(DWARFDie D) : Die(D) { - } + explicit iterator(DWARFDie D) : Die(D) {} iterator &operator++() { Die = Die.getSibling(); return *this; } + iterator operator++(int) { + auto Temp = *this; + Die = Die.getSibling(); + return Temp; + } + iterator &operator--() { Die = Die.getPreviousSibling(); return *this; } - explicit operator bool() const { return Die.isValid(); } - const DWARFDie &operator*() const { return Die; } + iterator operator--(int) { + auto Temp = *this; + Die = Die.getPreviousSibling(); + return Temp; + } + + 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; } }; Index: llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp =================================================================== --- llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -1085,19 +1085,55 @@ EXPECT_EQ(It, Begin); EXPECT_EQ(*It, B); - ++It; + It++; EXPECT_EQ(*It, C); ++It; EXPECT_EQ(*It, D); - ++It; + It++; EXPECT_EQ(It, End); --It; EXPECT_EQ(*It, D); - --It; + It--; EXPECT_EQ(*It, C); --It; EXPECT_EQ(*It, B); EXPECT_EQ(It, Begin); + + 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 : reverse(A)) { + 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) { @@ -1178,8 +1214,8 @@ DWARFDie Invalid; auto begin = Invalid.begin(); auto end = Invalid.end(); - EXPECT_FALSE(begin->isValid()); - EXPECT_FALSE(end->isValid()); + EXPECT_FALSE((*begin).isValid()); + EXPECT_FALSE((*end).isValid()); EXPECT_EQ(begin, end); } @@ -1648,13 +1684,13 @@ // and Val2-DIE refers to another one. auto DieDG = U->getUnitDIE(false); auto it = DieDG.begin(); - std::multimapgetAbbreviationDeclarationPtr())> DIEs; + std::multimap DIEs; const DWARFAbbreviationDeclaration *AbbrevPtrVal1 = nullptr; const DWARFAbbreviationDeclaration *AbbrevPtrVal2 = nullptr; for (; it != DieDG.end(); ++it) { - const auto *AbbrevPtr = it->getAbbreviationDeclarationPtr(); + const auto *AbbrevPtr = (*it).getAbbreviationDeclarationPtr(); EXPECT_TRUE((bool)AbbrevPtr); - auto FormValue = it->find(Attr); + auto FormValue = (*it).find(Attr); EXPECT_TRUE((bool)FormValue); const auto V = FormValue->getAsSignedConstant(); EXPECT_TRUE((bool)V);