1254721Semaste//===-- Block.cpp -----------------------------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#include "lldb/Symbol/Block.h"
10254721Semaste
11254721Semaste#include "lldb/Core/Module.h"
12254721Semaste#include "lldb/Core/Section.h"
13254721Semaste#include "lldb/Symbol/Function.h"
14254721Semaste#include "lldb/Symbol/SymbolFile.h"
15254721Semaste#include "lldb/Symbol/VariableList.h"
16321369Sdim#include "lldb/Utility/Log.h"
17254721Semaste
18353358Sdim#include <memory>
19353358Sdim
20254721Semasteusing namespace lldb;
21254721Semasteusing namespace lldb_private;
22254721Semaste
23314564SdimBlock::Block(lldb::user_id_t uid)
24314564Sdim    : UserID(uid), m_parent_scope(nullptr), m_children(), m_ranges(),
25314564Sdim      m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false),
26314564Sdim      m_parsed_block_variables(false), m_parsed_child_blocks(false) {}
27254721Semaste
28314564SdimBlock::~Block() {}
29254721Semaste
30314564Sdimvoid Block::GetDescription(Stream *s, Function *function,
31314564Sdim                           lldb::DescriptionLevel level, Target *target) const {
32314564Sdim  *s << "id = " << ((const UserID &)*this);
33254721Semaste
34314564Sdim  size_t num_ranges = m_ranges.GetSize();
35314564Sdim  if (num_ranges > 0) {
36254721Semaste
37314564Sdim    addr_t base_addr = LLDB_INVALID_ADDRESS;
38314564Sdim    if (target)
39314564Sdim      base_addr =
40314564Sdim          function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
41314564Sdim    if (base_addr == LLDB_INVALID_ADDRESS)
42314564Sdim      base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
43314564Sdim
44314564Sdim    s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
45314564Sdim    for (size_t i = 0; i < num_ranges; ++i) {
46314564Sdim      const Range &range = m_ranges.GetEntryRef(i);
47360784Sdim      DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
48360784Sdim                       base_addr + range.GetRangeEnd(), 4);
49254721Semaste    }
50314564Sdim  }
51254721Semaste
52314564Sdim  if (m_inlineInfoSP.get() != nullptr) {
53314564Sdim    bool show_fullpaths = (level == eDescriptionLevelVerbose);
54314564Sdim    m_inlineInfoSP->Dump(s, show_fullpaths);
55314564Sdim  }
56254721Semaste}
57254721Semaste
58314564Sdimvoid Block::Dump(Stream *s, addr_t base_addr, int32_t depth,
59314564Sdim                 bool show_context) const {
60314564Sdim  if (depth < 0) {
61314564Sdim    Block *parent = GetParent();
62314564Sdim    if (parent) {
63341825Sdim      // We have a depth that is less than zero, print our parent blocks first
64314564Sdim      parent->Dump(s, base_addr, depth + 1, show_context);
65254721Semaste    }
66314564Sdim  }
67254721Semaste
68314564Sdim  s->Printf("%p: ", static_cast<const void *>(this));
69314564Sdim  s->Indent();
70314564Sdim  *s << "Block" << static_cast<const UserID &>(*this);
71314564Sdim  const Block *parent_block = GetParent();
72314564Sdim  if (parent_block) {
73314564Sdim    s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
74314564Sdim  }
75314564Sdim  if (m_inlineInfoSP.get() != nullptr) {
76314564Sdim    bool show_fullpaths = false;
77314564Sdim    m_inlineInfoSP->Dump(s, show_fullpaths);
78314564Sdim  }
79254721Semaste
80314564Sdim  if (!m_ranges.IsEmpty()) {
81314564Sdim    *s << ", ranges =";
82276479Sdim
83314564Sdim    size_t num_ranges = m_ranges.GetSize();
84314564Sdim    for (size_t i = 0; i < num_ranges; ++i) {
85314564Sdim      const Range &range = m_ranges.GetEntryRef(i);
86344779Sdim      if (parent_block != nullptr && !parent_block->Contains(range))
87314564Sdim        *s << '!';
88314564Sdim      else
89314564Sdim        *s << ' ';
90360784Sdim      DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
91360784Sdim                       base_addr + range.GetRangeEnd(), 4);
92254721Semaste    }
93314564Sdim  }
94314564Sdim  s->EOL();
95254721Semaste
96314564Sdim  if (depth > 0) {
97314564Sdim    s->IndentMore();
98254721Semaste
99314564Sdim    if (m_variable_list_sp.get()) {
100314564Sdim      m_variable_list_sp->Dump(s, show_context);
101254721Semaste    }
102254721Semaste
103254721Semaste    collection::const_iterator pos, end = m_children.end();
104254721Semaste    for (pos = m_children.begin(); pos != end; ++pos)
105314564Sdim      (*pos)->Dump(s, base_addr, depth - 1, show_context);
106314564Sdim
107314564Sdim    s->IndentLess();
108314564Sdim  }
109254721Semaste}
110254721Semaste
111314564SdimBlock *Block::FindBlockByID(user_id_t block_id) {
112314564Sdim  if (block_id == GetID())
113314564Sdim    return this;
114314564Sdim
115314564Sdim  Block *matching_block = nullptr;
116314564Sdim  collection::const_iterator pos, end = m_children.end();
117314564Sdim  for (pos = m_children.begin(); pos != end; ++pos) {
118314564Sdim    matching_block = (*pos)->FindBlockByID(block_id);
119314564Sdim    if (matching_block)
120314564Sdim      break;
121314564Sdim  }
122314564Sdim  return matching_block;
123254721Semaste}
124254721Semaste
125314564Sdimvoid Block::CalculateSymbolContext(SymbolContext *sc) {
126314564Sdim  if (m_parent_scope)
127314564Sdim    m_parent_scope->CalculateSymbolContext(sc);
128314564Sdim  sc->block = this;
129254721Semaste}
130254721Semaste
131314564Sdimlldb::ModuleSP Block::CalculateSymbolContextModule() {
132314564Sdim  if (m_parent_scope)
133314564Sdim    return m_parent_scope->CalculateSymbolContextModule();
134314564Sdim  return lldb::ModuleSP();
135254721Semaste}
136254721Semaste
137314564SdimCompileUnit *Block::CalculateSymbolContextCompileUnit() {
138314564Sdim  if (m_parent_scope)
139314564Sdim    return m_parent_scope->CalculateSymbolContextCompileUnit();
140314564Sdim  return nullptr;
141254721Semaste}
142254721Semaste
143314564SdimFunction *Block::CalculateSymbolContextFunction() {
144314564Sdim  if (m_parent_scope)
145314564Sdim    return m_parent_scope->CalculateSymbolContextFunction();
146314564Sdim  return nullptr;
147254721Semaste}
148254721Semaste
149314564SdimBlock *Block::CalculateSymbolContextBlock() { return this; }
150314564Sdim
151314564Sdimvoid Block::DumpSymbolContext(Stream *s) {
152314564Sdim  Function *function = CalculateSymbolContextFunction();
153314564Sdim  if (function)
154314564Sdim    function->DumpSymbolContext(s);
155314564Sdim  s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());
156254721Semaste}
157254721Semaste
158314564Sdimvoid Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) {
159314564Sdim  if (!m_ranges.IsEmpty()) {
160314564Sdim    size_t num_ranges = m_ranges.GetSize();
161314564Sdim    for (size_t i = 0; i < num_ranges; ++i) {
162314564Sdim      const Range &range = m_ranges.GetEntryRef(i);
163360784Sdim      DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
164360784Sdim                       base_addr + range.GetRangeEnd(), 4);
165254721Semaste    }
166314564Sdim  }
167254721Semaste}
168254721Semaste
169314564Sdimbool Block::Contains(addr_t range_offset) const {
170314564Sdim  return m_ranges.FindEntryThatContains(range_offset) != nullptr;
171254721Semaste}
172254721Semaste
173314564Sdimbool Block::Contains(const Block *block) const {
174314564Sdim  if (this == block)
175314564Sdim    return false; // This block doesn't contain itself...
176314564Sdim
177314564Sdim  // Walk the parent chain for "block" and see if any if them match this block
178314564Sdim  const Block *block_parent;
179314564Sdim  for (block_parent = block->GetParent(); block_parent != nullptr;
180314564Sdim       block_parent = block_parent->GetParent()) {
181314564Sdim    if (this == block_parent)
182314564Sdim      return true; // One of the parents of "block" is this object!
183314564Sdim  }
184314564Sdim  return false;
185254721Semaste}
186254721Semaste
187314564Sdimbool Block::Contains(const Range &range) const {
188314564Sdim  return m_ranges.FindEntryThatContains(range) != nullptr;
189254721Semaste}
190254721Semaste
191314564SdimBlock *Block::GetParent() const {
192314564Sdim  if (m_parent_scope)
193314564Sdim    return m_parent_scope->CalculateSymbolContextBlock();
194314564Sdim  return nullptr;
195254721Semaste}
196254721Semaste
197314564SdimBlock *Block::GetContainingInlinedBlock() {
198314564Sdim  if (GetInlinedFunctionInfo())
199314564Sdim    return this;
200314564Sdim  return GetInlinedParent();
201254721Semaste}
202254721Semaste
203314564SdimBlock *Block::GetInlinedParent() {
204314564Sdim  Block *parent_block = GetParent();
205314564Sdim  if (parent_block) {
206314564Sdim    if (parent_block->GetInlinedFunctionInfo())
207314564Sdim      return parent_block;
208314564Sdim    else
209314564Sdim      return parent_block->GetInlinedParent();
210314564Sdim  }
211314564Sdim  return nullptr;
212254721Semaste}
213254721Semaste
214353358SdimBlock *Block::GetContainingInlinedBlockWithCallSite(
215353358Sdim    const Declaration &find_call_site) {
216353358Sdim  Block *inlined_block = GetContainingInlinedBlock();
217353358Sdim
218353358Sdim  while (inlined_block) {
219353358Sdim    const auto *function_info = inlined_block->GetInlinedFunctionInfo();
220353358Sdim
221353358Sdim    if (function_info &&
222353358Sdim        function_info->GetCallSite().FileAndLineEqual(find_call_site))
223353358Sdim      return inlined_block;
224353358Sdim    inlined_block = inlined_block->GetInlinedParent();
225353358Sdim  }
226353358Sdim  return nullptr;
227353358Sdim}
228353358Sdim
229314564Sdimbool Block::GetRangeContainingOffset(const addr_t offset, Range &range) {
230314564Sdim  const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
231314564Sdim  if (range_ptr) {
232314564Sdim    range = *range_ptr;
233314564Sdim    return true;
234314564Sdim  }
235314564Sdim  range.Clear();
236314564Sdim  return false;
237254721Semaste}
238254721Semaste
239314564Sdimbool Block::GetRangeContainingAddress(const Address &addr,
240314564Sdim                                      AddressRange &range) {
241314564Sdim  Function *function = CalculateSymbolContextFunction();
242314564Sdim  if (function) {
243314564Sdim    const AddressRange &func_range = function->GetAddressRange();
244314564Sdim    if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
245314564Sdim      const addr_t addr_offset = addr.GetOffset();
246314564Sdim      const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
247314564Sdim      if (addr_offset >= func_offset &&
248314564Sdim          addr_offset < func_offset + func_range.GetByteSize()) {
249314564Sdim        addr_t offset = addr_offset - func_offset;
250254721Semaste
251314564Sdim        const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
252254721Semaste
253314564Sdim        if (range_ptr) {
254314564Sdim          range.GetBaseAddress() = func_range.GetBaseAddress();
255314564Sdim          range.GetBaseAddress().SetOffset(func_offset +
256314564Sdim                                           range_ptr->GetRangeBase());
257314564Sdim          range.SetByteSize(range_ptr->GetByteSize());
258314564Sdim          return true;
259254721Semaste        }
260314564Sdim      }
261254721Semaste    }
262314564Sdim  }
263314564Sdim  range.Clear();
264314564Sdim  return false;
265254721Semaste}
266254721Semaste
267314564Sdimbool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,
268314564Sdim                                          Target &target, AddressRange &range) {
269314564Sdim  Address load_address;
270314564Sdim  load_address.SetLoadAddress(load_addr, &target);
271314564Sdim  AddressRange containing_range;
272314564Sdim  return GetRangeContainingAddress(load_address, containing_range);
273254721Semaste}
274254721Semaste
275314564Sdimuint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
276314564Sdim  Function *function = CalculateSymbolContextFunction();
277314564Sdim  if (function) {
278314564Sdim    const AddressRange &func_range = function->GetAddressRange();
279314564Sdim    if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
280314564Sdim      const addr_t addr_offset = addr.GetOffset();
281314564Sdim      const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
282314564Sdim      if (addr_offset >= func_offset &&
283314564Sdim          addr_offset < func_offset + func_range.GetByteSize()) {
284314564Sdim        addr_t offset = addr_offset - func_offset;
285314564Sdim        return m_ranges.FindEntryIndexThatContains(offset);
286314564Sdim      }
287314564Sdim    }
288314564Sdim  }
289314564Sdim  return UINT32_MAX;
290314564Sdim}
291254721Semaste
292314564Sdimbool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
293314564Sdim  if (range_idx < m_ranges.GetSize()) {
294254721Semaste    Function *function = CalculateSymbolContextFunction();
295314564Sdim    if (function) {
296314564Sdim      const Range &vm_range = m_ranges.GetEntryRef(range_idx);
297314564Sdim      range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
298314564Sdim      range.GetBaseAddress().Slide(vm_range.GetRangeBase());
299314564Sdim      range.SetByteSize(vm_range.GetByteSize());
300314564Sdim      return true;
301254721Semaste    }
302314564Sdim  }
303314564Sdim  return false;
304254721Semaste}
305254721Semaste
306314564Sdimbool Block::GetStartAddress(Address &addr) {
307314564Sdim  if (m_ranges.IsEmpty())
308254721Semaste    return false;
309254721Semaste
310314564Sdim  Function *function = CalculateSymbolContextFunction();
311314564Sdim  if (function) {
312314564Sdim    addr = function->GetAddressRange().GetBaseAddress();
313314564Sdim    addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase());
314314564Sdim    return true;
315314564Sdim  }
316314564Sdim  return false;
317254721Semaste}
318254721Semaste
319314564Sdimvoid Block::FinalizeRanges() {
320314564Sdim  m_ranges.Sort();
321314564Sdim  m_ranges.CombineConsecutiveRanges();
322254721Semaste}
323254721Semaste
324314564Sdimvoid Block::AddRange(const Range &range) {
325314564Sdim  Block *parent_block = GetParent();
326314564Sdim  if (parent_block && !parent_block->Contains(range)) {
327314564Sdim    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS));
328314564Sdim    if (log) {
329314564Sdim      ModuleSP module_sp(m_parent_scope->CalculateSymbolContextModule());
330314564Sdim      Function *function = m_parent_scope->CalculateSymbolContextFunction();
331314564Sdim      const addr_t function_file_addr =
332314564Sdim          function->GetAddressRange().GetBaseAddress().GetFileAddress();
333314564Sdim      const addr_t block_start_addr = function_file_addr + range.GetRangeBase();
334314564Sdim      const addr_t block_end_addr = function_file_addr + range.GetRangeEnd();
335314564Sdim      Type *func_type = function->GetType();
336314564Sdim
337314564Sdim      const Declaration &func_decl = func_type->GetDeclaration();
338314564Sdim      if (func_decl.GetLine()) {
339360784Sdim        LLDB_LOGF(log,
340360784Sdim                  "warning: %s:%u block {0x%8.8" PRIx64
341360784Sdim                  "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64
342360784Sdim                  ") which is not contained in parent block {0x%8.8" PRIx64
343360784Sdim                  "} in function {0x%8.8" PRIx64 "} from %s",
344360784Sdim                  func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(),
345360784Sdim                  GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
346360784Sdim                  block_end_addr, parent_block->GetID(), function->GetID(),
347360784Sdim                  module_sp->GetFileSpec().GetPath().c_str());
348314564Sdim      } else {
349360784Sdim        LLDB_LOGF(log,
350360784Sdim                  "warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64
351360784Sdim                  " - 0x%" PRIx64
352360784Sdim                  ") which is not contained in parent block {0x%8.8" PRIx64
353360784Sdim                  "} in function {0x%8.8" PRIx64 "} from %s",
354360784Sdim                  GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
355360784Sdim                  block_end_addr, parent_block->GetID(), function->GetID(),
356360784Sdim                  module_sp->GetFileSpec().GetPath().c_str());
357314564Sdim      }
358254721Semaste    }
359314564Sdim    parent_block->AddRange(range);
360314564Sdim  }
361314564Sdim  m_ranges.Append(range);
362254721Semaste}
363254721Semaste
364254721Semaste// Return the current number of bytes that this object occupies in memory
365314564Sdimsize_t Block::MemorySize() const {
366314564Sdim  size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);
367314564Sdim  if (m_inlineInfoSP.get())
368314564Sdim    mem_size += m_inlineInfoSP->MemorySize();
369314564Sdim  if (m_variable_list_sp.get())
370314564Sdim    mem_size += m_variable_list_sp->MemorySize();
371314564Sdim  return mem_size;
372254721Semaste}
373254721Semaste
374314564Sdimvoid Block::AddChild(const BlockSP &child_block_sp) {
375314564Sdim  if (child_block_sp) {
376314564Sdim    child_block_sp->SetParentScope(this);
377314564Sdim    m_children.push_back(child_block_sp);
378314564Sdim  }
379254721Semaste}
380254721Semaste
381314564Sdimvoid Block::SetInlinedFunctionInfo(const char *name, const char *mangled,
382314564Sdim                                   const Declaration *decl_ptr,
383314564Sdim                                   const Declaration *call_decl_ptr) {
384353358Sdim  m_inlineInfoSP = std::make_shared<InlineFunctionInfo>(name, mangled, decl_ptr,
385353358Sdim                                                        call_decl_ptr);
386254721Semaste}
387254721Semaste
388314564SdimVariableListSP Block::GetBlockVariableList(bool can_create) {
389344779Sdim  if (!m_parsed_block_variables) {
390314564Sdim    if (m_variable_list_sp.get() == nullptr && can_create) {
391314564Sdim      m_parsed_block_variables = true;
392314564Sdim      SymbolContext sc;
393314564Sdim      CalculateSymbolContext(&sc);
394314564Sdim      assert(sc.module_sp);
395360784Sdim      sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc);
396254721Semaste    }
397314564Sdim  }
398314564Sdim  return m_variable_list_sp;
399254721Semaste}
400254721Semaste
401254721Semasteuint32_t
402314564SdimBlock::AppendBlockVariables(bool can_create, bool get_child_block_variables,
403314564Sdim                            bool stop_if_child_block_is_inlined_function,
404314564Sdim                            const std::function<bool(Variable *)> &filter,
405314564Sdim                            VariableList *variable_list) {
406314564Sdim  uint32_t num_variables_added = 0;
407314564Sdim  VariableList *block_var_list = GetBlockVariableList(can_create).get();
408314564Sdim  if (block_var_list) {
409360784Sdim    for (const VariableSP &var_sp : *block_var_list) {
410360784Sdim      if (filter(var_sp.get())) {
411314564Sdim        num_variables_added++;
412360784Sdim        variable_list->AddVariable(var_sp);
413314564Sdim      }
414254721Semaste    }
415314564Sdim  }
416309124Sdim
417314564Sdim  if (get_child_block_variables) {
418314564Sdim    collection::const_iterator pos, end = m_children.end();
419314564Sdim    for (pos = m_children.begin(); pos != end; ++pos) {
420314564Sdim      Block *child_block = pos->get();
421344779Sdim      if (!stop_if_child_block_is_inlined_function ||
422314564Sdim          child_block->GetInlinedFunctionInfo() == nullptr) {
423314564Sdim        num_variables_added += child_block->AppendBlockVariables(
424314564Sdim            can_create, get_child_block_variables,
425314564Sdim            stop_if_child_block_is_inlined_function, filter, variable_list);
426314564Sdim      }
427254721Semaste    }
428314564Sdim  }
429314564Sdim  return num_variables_added;
430254721Semaste}
431254721Semaste
432314564Sdimuint32_t Block::AppendVariables(bool can_create, bool get_parent_variables,
433314564Sdim                                bool stop_if_block_is_inlined_function,
434314564Sdim                                const std::function<bool(Variable *)> &filter,
435314564Sdim                                VariableList *variable_list) {
436314564Sdim  uint32_t num_variables_added = 0;
437314564Sdim  VariableListSP variable_list_sp(GetBlockVariableList(can_create));
438254721Semaste
439314564Sdim  bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;
440314564Sdim  if (variable_list_sp) {
441314564Sdim    for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) {
442314564Sdim      VariableSP variable = variable_list_sp->GetVariableAtIndex(i);
443314564Sdim      if (filter(variable.get())) {
444314564Sdim        num_variables_added++;
445314564Sdim        variable_list->AddVariable(variable);
446314564Sdim      }
447254721Semaste    }
448314564Sdim  }
449309124Sdim
450314564Sdim  if (get_parent_variables) {
451314564Sdim    if (stop_if_block_is_inlined_function && is_inlined_function)
452314564Sdim      return num_variables_added;
453314564Sdim
454314564Sdim    Block *parent_block = GetParent();
455314564Sdim    if (parent_block)
456314564Sdim      num_variables_added += parent_block->AppendVariables(
457314564Sdim          can_create, get_parent_variables, stop_if_block_is_inlined_function,
458314564Sdim          filter, variable_list);
459314564Sdim  }
460314564Sdim  return num_variables_added;
461254721Semaste}
462254721Semaste
463344779SdimSymbolFile *Block::GetSymbolFile() {
464344779Sdim  if (ModuleSP module_sp = CalculateSymbolContextModule())
465360784Sdim    return module_sp->GetSymbolFile();
466344779Sdim  return nullptr;
467344779Sdim}
468344779Sdim
469314564SdimCompilerDeclContext Block::GetDeclContext() {
470344779Sdim  if (SymbolFile *sym_file = GetSymbolFile())
471344779Sdim    return sym_file->GetDeclContextForUID(GetID());
472314564Sdim  return CompilerDeclContext();
473254721Semaste}
474254721Semaste
475314564Sdimvoid Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) {
476314564Sdim  m_parsed_block_info = b;
477314564Sdim  if (set_children) {
478314564Sdim    m_parsed_child_blocks = true;
479314564Sdim    collection::const_iterator pos, end = m_children.end();
480314564Sdim    for (pos = m_children.begin(); pos != end; ++pos)
481314564Sdim      (*pos)->SetBlockInfoHasBeenParsed(b, true);
482314564Sdim  }
483254721Semaste}
484254721Semaste
485314564Sdimvoid Block::SetDidParseVariables(bool b, bool set_children) {
486314564Sdim  m_parsed_block_variables = b;
487314564Sdim  if (set_children) {
488314564Sdim    collection::const_iterator pos, end = m_children.end();
489314564Sdim    for (pos = m_children.begin(); pos != end; ++pos)
490314564Sdim      (*pos)->SetDidParseVariables(b, true);
491314564Sdim  }
492254721Semaste}
493254721Semaste
494314564SdimBlock *Block::GetSibling() const {
495314564Sdim  if (m_parent_scope) {
496314564Sdim    Block *parent_block = GetParent();
497314564Sdim    if (parent_block)
498314564Sdim      return parent_block->GetSiblingForChild(this);
499314564Sdim  }
500314564Sdim  return nullptr;
501254721Semaste}
502254721Semaste// A parent of child blocks can be asked to find a sibling block given
503254721Semaste// one of its child blocks
504314564SdimBlock *Block::GetSiblingForChild(const Block *child_block) const {
505314564Sdim  if (!m_children.empty()) {
506314564Sdim    collection::const_iterator pos, end = m_children.end();
507314564Sdim    for (pos = m_children.begin(); pos != end; ++pos) {
508314564Sdim      if (pos->get() == child_block) {
509314564Sdim        if (++pos != end)
510314564Sdim          return pos->get();
511314564Sdim        break;
512314564Sdim      }
513254721Semaste    }
514314564Sdim  }
515314564Sdim  return nullptr;
516254721Semaste}
517