[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-08-04 Thread walter erquinigo via Phabricator via lldb-commits
wallace added a comment.

I found the issue: https://reviews.llvm.org/D107434


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103172/new/

https://reviews.llvm.org/D103172

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-08-04 Thread walter erquinigo via Phabricator via lldb-commits
wallace added subscribers: clayborg, wallace.
wallace added a comment.

This breaks debugging in many cases :( Many of my users started reporting 
crashes in LLDB when setting source line breakpoints.

For example, a simple command like `(lldb) b TransAttr.cpp:758` causes a crash 
and has the following stack trace

  thread #1, name = 'lldb', stop reason = signal SIGSEGV: invalid address 
(fault address: 0x10)
   * frame #0: 0x7f1c2b642caa 
liblldb.so.14`DWARFUnit::GetSymbolFileDWARF(this=0x) const at 
DWARFUnit.h:194:56
 frame #1: 0x7f1c2bd46ce4 
liblldb.so.14`SymbolFileDWARF::GetTypeSystem(unit=0x) at 
SymbolFileDWARF.cpp:3880:15
 frame #2: 0x7f1c2bd3b29b 
liblldb.so.14`SymbolFileDWARF::GetDWARFParser(unit=0x) at 
SymbolFileDWARF.cpp:3884:29
 frame #3: 0x7f1c2bd8cb87 
liblldb.so.14`DWARFASTParserClang::CopyUniqueClassMethodTypes(this=0x01eaa920,
 src_class_die=0x7ffe9ff0ff38, dst_class_die=0x7ffe9ff0fe48, 
class_type=0x01d42c10, failures=size=0) at 
DWARFASTParserClang.cpp:3572:11
 frame #4: 0x7f1c2bd891fd 
liblldb.so.14`DWARFASTParserClang::ParseSubroutine(this=0x01eaa920, 
die=0x7ffe9ff10778, attrs=0x7ffe9ff101b0) at 
DWARFASTParserClang.cpp:1025:15
 frame #5: 0x7f1c2bd85080 
liblldb.so.14`DWARFASTParserClang::ParseTypeFromDWARF(this=0x01eaa920, 
sc=0x7ffe9ff105d0, die=0x7ffe9ff10778, 
type_is_new_ptr=0x) at DWARFASTParserClang.cpp:522:15
 frame #6: 0x7f1c2bd401fb 
liblldb.so.14`SymbolFileDWARF::ParseType(this=0x004610a0, 
sc=0x7ffe9ff105d0, die=0x7ffe9ff10778, 
type_is_new_ptr=0x) at SymbolFileDWARF.cpp:2946:31
 frame #7: 0x7f1c2bd3b70f 
liblldb.so.14`SymbolFileDWARF::GetTypeForDIE(this=0x004610a0, 
die=0x7ffe9ff10778, resolve_function_context=false) at 
SymbolFileDWARF.cpp:2560:17
 frame #8: 0x7f1c2bd3a4bd 
liblldb.so.14`SymbolFileDWARF::ResolveType(this=0x004610a0, 
die=0x7ffe9ff10778, assert_not_being_parsed=true, 
resolve_function_context=false) at SymbolFileDWARF.cpp:1568:18
 frame #9: 0x7f1c2bd17500 
liblldb.so.14`DWARFDIE::ResolveType(this=0x7ffe9ff10778) const at 
DWARFDIE.cpp:350:24
 frame #10: 0x7f1c2bd3a365 
liblldb.so.14`SymbolFileDWARF::ResolveTypeUID(this=0x004610a0, 
type_uid=57283337) at SymbolFileDWARF.cpp:1437:21
 frame #11: 0x7f1c2b73037e 
liblldb.so.14`lldb_private::Function::GetType(this=0x01cd5ed0) at 
Function.cpp:515:24
 frame #12: 0x7f1c2b73017a 
liblldb.so.14`lldb_private::Function::GetStartLineSourceInfo(this=0x01cd5ed0,
 source_file=0x7ffe9ff109e0, line_no=0x7ffe9ff109dc) at 
Function.cpp:252:3
 frame #13: 0x7f1c2b515a5e 
liblldb.so.14`lldb_private::BreakpointResolverFileLine::FilterContexts(this=0x01f61c00,
 sc_list=0x7ffe9ff10d00, is_relative=true) at 
BreakpointResolverFileLine.cpp:162:20
 frame #14: 0x7f1c2b5163d3 
liblldb.so.14`lldb_private::BreakpointResolverFileLine::SearchCallback(this=0x01f61c00,
 filter=0x01fab770, context=0x7ffe9ff10d68, 
addr=0x) at BreakpointResolverFileLine.cpp:254:3
 frame #15: 0x7f1c2b5cae2a 
liblldb.so.14`lldb_private::SearchFilter::DoModuleIteration(this=0x01fab770,
 context=0x7ffe9ff10f28, searcher=0x01f61c00) at 
SearchFilter.cpp:271:20
 frame #16: 0x7f1c2b5cabb9 
liblldb.so.14`lldb_private::SearchFilter::Search(this=0x01fab770, 
searcher=0x01f61c00) at SearchFilter.cpp:216:3
 frame #17: 0x7f1c2b50c24e 
liblldb.so.14`lldb_private::BreakpointResolver::ResolveBreakpoint(this=0x01f61c00,
 filter=0x01fab770) at BreakpointResolver.cpp:177:10
 frame #18: 0x7f1c2b4e93e6 
liblldb.so.14`lldb_private::Breakpoint::ResolveBreakpoint(this=0x003c76d0)
 at Breakpoint.cpp:443:20
 frame #19: 0x7f1c2b851596 
liblldb.so.14`lldb_private::Target::AddBreakpoint(this=0x0044dad0, 
bp_sp=std::__shared_ptr::element_type @ 0x003c76d0, internal=false) at 
Target.cpp:662:10
 frame #20: 0x7f1c2b852f64 
liblldb.so.14`lldb_private::Target::CreateBreakpoint(this=0x0044dad0, 
filter_sp=std::__shared_ptr::element_type @ 0x01fab770, 
resolver_sp=std::__shared_ptr::element_type @ 0x01f61c00, internal=false, 
request_hardware=false, resolve_indirect_symbols=true) at Target.cpp:641:5
 frame #21: 0x7f1c2b85342f 
liblldb.so.14`lldb_private::Target::CreateBreakpoint(this=0x0044dad0, 
containingModules=0x00348b80, file=0x7ffe9ff11768, line_no=758, 
column=0, offset=0, check_inlines=eLazyBoolYes, skip_prologue=eLazyBoolYes, 
internal=false, hardware=false, move_to_nearest_code=eLazyBoolYes) at 
Target.cpp:384:10
 frame #22: 0x7f1c2d6895f0 
liblldb.so.14`CommandObjectBreakpointSet::DoExecute(this=0x00348750, 

[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-07-22 Thread David Blaikie via Phabricator via lldb-commits
dblaikie added inline comments.



Comment at: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h:97-105
+  template 
+  llvm::iterator_range children() const {
+return llvm::make_range(T(*this), T());
+  }
+};
+
+class DWARFDIE::child_iterator

rather than a temeplate, what if it were code something like this: 
https://godbolt.org/z/3abeK3EPx ?



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103172/new/

https://reviews.llvm.org/D103172

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-07-22 Thread Raphael Isemann via Phabricator via lldb-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG77440d644b3b: [lldb][NFC] Allow range-based for loops over 
DWARFDIEs children (authored by teemperor).
Herald added a subscriber: lldb-commits.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103172/new/

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
  lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
  lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp

Index: lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
===
--- /dev/null
+++ lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
@@ -0,0 +1,105 @@
+//===-- DWARFDIETest.cpp --=---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "TestingSupport/Symbol/YAMLModuleTester.h"
+#include "llvm/ADT/STLExtras.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+TEST(DWARFDIETest, ChildIteration) {
+  // Tests DWARFDIE::child_iterator.
+
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:ELFDATA2LSB
+  Type:ET_EXEC
+  Machine: EM_386
+DWARF:
+  debug_abbrev:
+- Table:
+- Code:0x0001
+  Tag: DW_TAG_compile_unit
+  Children:DW_CHILDREN_yes
+  Attributes:
+- Attribute:   DW_AT_language
+  Form:DW_FORM_data2
+- Code:0x0002
+  Tag: DW_TAG_base_type
+  Children:DW_CHILDREN_no
+  Attributes:
+- Attribute:   DW_AT_encoding
+  Form:DW_FORM_data1
+- Attribute:   DW_AT_byte_size
+  Form:DW_FORM_data1
+  debug_info:
+- Version: 4
+  AddrSize:8
+  Entries:
+- AbbrCode:0x0001
+  Values:
+- Value:   0x000C
+- AbbrCode:0x0002
+  Values:
+- Value:   0x0007 # DW_ATE_unsigned
+- Value:   0x0004
+- AbbrCode:0x0002
+  Values:
+- Value:   0x0007 # DW_ATE_unsigned
+- Value:   0x0008
+- AbbrCode:0x0002
+  Values:
+- Value:   0x0005 # DW_ATE_signed
+- Value:   0x0008
+- AbbrCode:0x
+)";
+
+  YAMLModuleTester t(yamldata);
+  ASSERT_TRUE((bool)t.GetDwarfUnit());
+
+  DWARFUnit *unit = t.GetDwarfUnit();
+  const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE();
+
+  // Create a DWARFDIE that has three DW_TAG_base_type children.
+  DWARFDIE top_die(unit, die_first);
+
+  // Create the iterator range that has the three tags as elements.
+  llvm::iterator_range children = top_die.children();
+
+  // Compare begin() to the first child DIE.
+  DWARFDIE::child_iterator child_iter = children.begin();
+  ASSERT_NE(child_iter, children.end());
+  const DWARFDebugInfoEntry *die_child0 = die_first->GetFirstChild();
+  EXPECT_EQ((*child_iter).GetDIE(), die_child0);
+
+  // Step to the second child DIE.
+  ++child_iter;
+  ASSERT_NE(child_iter, children.end());
+  const DWARFDebugInfoEntry *die_child1 = die_child0->GetSibling();
+  EXPECT_EQ((*child_iter).GetDIE(), die_child1);
+
+  // Step to the third child DIE.
+  ++child_iter;
+  ASSERT_NE(child_iter, children.end());
+  const DWARFDebugInfoEntry *die_child2 = die_child1->GetSibling();
+  EXPECT_EQ((*child_iter).GetDIE(), die_child2);
+
+  // Step to the end of the range.
+  ++child_iter;
+  EXPECT_EQ(child_iter, children.end());
+
+  // Take one of the DW_TAG_base_type DIEs (which has no children) and make
+  // sure the children range is now empty.
+  DWARFDIE no_children_die(unit, die_child0);
+  EXPECT_TRUE(no_children_die.children().empty());
+}
Index: lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
===
--- lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
+++ lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_lldb_unittest(SymbolFileDWARFTests
   DWARFASTParserClangTests.cpp
+  DWARFDIETest.cpp
   DWARFUnitTest.cpp
   

[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-07-07 Thread Jonas Devlieghere via Phabricator via lldb-commits
JDevlieghere accepted this revision.
JDevlieghere added a comment.

LGTM


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103172/new/

https://reviews.llvm.org/D103172

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-07-06 Thread Raphael Isemann via Phabricator via lldb-commits
teemperor added a comment.

ping.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103172/new/

https://reviews.llvm.org/D103172

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-06-17 Thread Raphael Isemann via Phabricator via lldb-commits
teemperor added inline comments.



Comment at: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h:117
+// (CU, (DIE)nullptr) == (nullptr, nullptr) -> true
+if (!m_die.IsValid() && !it.m_die.IsValid())
+  return true;

shafik wrote:
> I think:
> 
> ```
> bool operator==(const DWARFBaseDIE , const DWARFBaseDIE ) {
>   return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
> }
> ```
> 
> will do the same thing but maybe I am confused.
> 
> Maybe we should have a unit test?
That's the `DWARFDIE::operator==` implementation called below and this special 
case is because of the comment one line above (we need to match the end 
iterator if it's default constructed when `GetSibling()` returns a DWARFDIE 
that has a valid CU but a `null` DIE).


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103172/new/

https://reviews.llvm.org/D103172

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-06-17 Thread Raphael Isemann via Phabricator via lldb-commits
teemperor updated this revision to Diff 352666.
teemperor added a comment.
Herald added a subscriber: mgorny.

- Added a unit test (thanks Shafik!)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103172/new/

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
  lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
  lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp

Index: lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
===
--- /dev/null
+++ lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
@@ -0,0 +1,105 @@
+//===-- DWARFDIETest.cpp --=---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "TestingSupport/Symbol/YAMLModuleTester.h"
+#include "llvm/ADT/STLExtras.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+TEST(DWARFDIETest, ChildIteration) {
+  // Tests DWARFDIE::child_iterator.
+
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:ELFDATA2LSB
+  Type:ET_EXEC
+  Machine: EM_386
+DWARF:
+  debug_abbrev:
+- Table:
+- Code:0x0001
+  Tag: DW_TAG_compile_unit
+  Children:DW_CHILDREN_yes
+  Attributes:
+- Attribute:   DW_AT_language
+  Form:DW_FORM_data2
+- Code:0x0002
+  Tag: DW_TAG_base_type
+  Children:DW_CHILDREN_no
+  Attributes:
+- Attribute:   DW_AT_encoding
+  Form:DW_FORM_data1
+- Attribute:   DW_AT_byte_size
+  Form:DW_FORM_data1
+  debug_info:
+- Version: 4
+  AddrSize:8
+  Entries:
+- AbbrCode:0x0001
+  Values:
+- Value:   0x000C
+- AbbrCode:0x0002
+  Values:
+- Value:   0x0007 # DW_ATE_unsigned
+- Value:   0x0004
+- AbbrCode:0x0002
+  Values:
+- Value:   0x0007 # DW_ATE_unsigned
+- Value:   0x0008
+- AbbrCode:0x0002
+  Values:
+- Value:   0x0005 # DW_ATE_signed
+- Value:   0x0008
+- AbbrCode:0x
+)";
+
+  YAMLModuleTester t(yamldata);
+  ASSERT_TRUE((bool)t.GetDwarfUnit());
+
+  DWARFUnit *unit = t.GetDwarfUnit();
+  const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE();
+
+  // Create a DWARFDIE that has three DW_TAG_base_type children.
+  DWARFDIE top_die(unit, die_first);
+
+  // Create the iterator range that has the three tags as elements.
+  llvm::iterator_range children = top_die.children();
+
+  // Compare begin() to the first child DIE.
+  DWARFDIE::child_iterator child_iter = children.begin();
+  ASSERT_NE(child_iter, children.end());
+  const DWARFDebugInfoEntry *die_child0 = die_first->GetFirstChild();
+  EXPECT_EQ((*child_iter).GetDIE(), die_child0);
+
+  // Step to the second child DIE.
+  ++child_iter;
+  ASSERT_NE(child_iter, children.end());
+  const DWARFDebugInfoEntry *die_child1 = die_child0->GetSibling();
+  EXPECT_EQ((*child_iter).GetDIE(), die_child1);
+
+  // Step to the third child DIE.
+  ++child_iter;
+  ASSERT_NE(child_iter, children.end());
+  const DWARFDebugInfoEntry *die_child2 = die_child1->GetSibling();
+  EXPECT_EQ((*child_iter).GetDIE(), die_child2);
+
+  // Step to the end of the range.
+  ++child_iter;
+  EXPECT_EQ(child_iter, children.end());
+
+  // Take one of the DW_TAG_base_type DIEs (which has no children) and make
+  // sure the children range is now empty.
+  DWARFDIE no_children_die(unit, die_child0);
+  EXPECT_TRUE(no_children_die.children().empty());
+}
Index: lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
===
--- lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
+++ lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_lldb_unittest(SymbolFileDWARFTests
   DWARFASTParserClangTests.cpp
+  DWARFDIETest.cpp
   DWARFUnitTest.cpp
   SymbolFileDWARFTests.cpp
   XcodeSDKModuleTests.cpp
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===

[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-05-26 Thread Shafik Yaghmour via Phabricator via lldb-commits
shafik added inline comments.



Comment at: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h:117
+// (CU, (DIE)nullptr) == (nullptr, nullptr) -> true
+if (!m_die.IsValid() && !it.m_die.IsValid())
+  return true;

I think:

```
bool operator==(const DWARFBaseDIE , const DWARFBaseDIE ) {
  return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
}
```

will do the same thing but maybe I am confused.

Maybe we should have a unit test?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103172/new/

https://reviews.llvm.org/D103172

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D103172: [lldb][NFC] Allow range-based for loops over DWARFDIE's children

2021-05-26 Thread Raphael Isemann via Phabricator via lldb-commits
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 _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> 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 _line, int _column, int _file,
 int _line, int _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 
+  llvm::iterator_range children() const {
+return llvm::make_range(T(*this), T());
+  }
+};
+
+class DWARFDIE::child_iterator
+: public llvm::iterator_facade_base {
+  /// The current child or an invalid DWARFDie.
+  DWARFDIE m_die;
+
+public:
+  child_iterator() = default;
+  child_iterator(const DWARFDIE ) : m_die(parent.GetFirstChild()) {}
+  bool operator==(const child_iterator ) 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'
+