1dda28197Spatrick //===-- Block.cpp ---------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Symbol/Block.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/Core/Module.h"
12061da546Spatrick #include "lldb/Core/Section.h"
13061da546Spatrick #include "lldb/Symbol/Function.h"
14061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
15061da546Spatrick #include "lldb/Symbol/VariableList.h"
16*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
17061da546Spatrick #include "lldb/Utility/Log.h"
18061da546Spatrick
19061da546Spatrick #include <memory>
20061da546Spatrick
21061da546Spatrick using namespace lldb;
22061da546Spatrick using namespace lldb_private;
23061da546Spatrick
Block(lldb::user_id_t uid)24061da546Spatrick Block::Block(lldb::user_id_t uid)
25061da546Spatrick : UserID(uid), m_parent_scope(nullptr), m_children(), m_ranges(),
26061da546Spatrick m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false),
27061da546Spatrick m_parsed_block_variables(false), m_parsed_child_blocks(false) {}
28061da546Spatrick
29be691f3bSpatrick Block::~Block() = default;
30061da546Spatrick
GetDescription(Stream * s,Function * function,lldb::DescriptionLevel level,Target * target) const31061da546Spatrick void Block::GetDescription(Stream *s, Function *function,
32061da546Spatrick lldb::DescriptionLevel level, Target *target) const {
33061da546Spatrick *s << "id = " << ((const UserID &)*this);
34061da546Spatrick
35061da546Spatrick size_t num_ranges = m_ranges.GetSize();
36061da546Spatrick if (num_ranges > 0) {
37061da546Spatrick
38061da546Spatrick addr_t base_addr = LLDB_INVALID_ADDRESS;
39061da546Spatrick if (target)
40061da546Spatrick base_addr =
41061da546Spatrick function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
42061da546Spatrick if (base_addr == LLDB_INVALID_ADDRESS)
43061da546Spatrick base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
44061da546Spatrick
45061da546Spatrick s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
46061da546Spatrick for (size_t i = 0; i < num_ranges; ++i) {
47061da546Spatrick const Range &range = m_ranges.GetEntryRef(i);
48061da546Spatrick DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
49061da546Spatrick base_addr + range.GetRangeEnd(), 4);
50061da546Spatrick }
51061da546Spatrick }
52061da546Spatrick
53061da546Spatrick if (m_inlineInfoSP.get() != nullptr) {
54061da546Spatrick bool show_fullpaths = (level == eDescriptionLevelVerbose);
55061da546Spatrick m_inlineInfoSP->Dump(s, show_fullpaths);
56061da546Spatrick }
57061da546Spatrick }
58061da546Spatrick
Dump(Stream * s,addr_t base_addr,int32_t depth,bool show_context) const59061da546Spatrick void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,
60061da546Spatrick bool show_context) const {
61061da546Spatrick if (depth < 0) {
62061da546Spatrick Block *parent = GetParent();
63061da546Spatrick if (parent) {
64061da546Spatrick // We have a depth that is less than zero, print our parent blocks first
65061da546Spatrick parent->Dump(s, base_addr, depth + 1, show_context);
66061da546Spatrick }
67061da546Spatrick }
68061da546Spatrick
69061da546Spatrick s->Printf("%p: ", static_cast<const void *>(this));
70061da546Spatrick s->Indent();
71061da546Spatrick *s << "Block" << static_cast<const UserID &>(*this);
72061da546Spatrick const Block *parent_block = GetParent();
73061da546Spatrick if (parent_block) {
74061da546Spatrick s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
75061da546Spatrick }
76061da546Spatrick if (m_inlineInfoSP.get() != nullptr) {
77061da546Spatrick bool show_fullpaths = false;
78061da546Spatrick m_inlineInfoSP->Dump(s, show_fullpaths);
79061da546Spatrick }
80061da546Spatrick
81061da546Spatrick if (!m_ranges.IsEmpty()) {
82061da546Spatrick *s << ", ranges =";
83061da546Spatrick
84061da546Spatrick size_t num_ranges = m_ranges.GetSize();
85061da546Spatrick for (size_t i = 0; i < num_ranges; ++i) {
86061da546Spatrick const Range &range = m_ranges.GetEntryRef(i);
87061da546Spatrick if (parent_block != nullptr && !parent_block->Contains(range))
88061da546Spatrick *s << '!';
89061da546Spatrick else
90061da546Spatrick *s << ' ';
91061da546Spatrick DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
92061da546Spatrick base_addr + range.GetRangeEnd(), 4);
93061da546Spatrick }
94061da546Spatrick }
95061da546Spatrick s->EOL();
96061da546Spatrick
97061da546Spatrick if (depth > 0) {
98061da546Spatrick s->IndentMore();
99061da546Spatrick
100061da546Spatrick if (m_variable_list_sp.get()) {
101061da546Spatrick m_variable_list_sp->Dump(s, show_context);
102061da546Spatrick }
103061da546Spatrick
104061da546Spatrick collection::const_iterator pos, end = m_children.end();
105061da546Spatrick for (pos = m_children.begin(); pos != end; ++pos)
106061da546Spatrick (*pos)->Dump(s, base_addr, depth - 1, show_context);
107061da546Spatrick
108061da546Spatrick s->IndentLess();
109061da546Spatrick }
110061da546Spatrick }
111061da546Spatrick
FindBlockByID(user_id_t block_id)112061da546Spatrick Block *Block::FindBlockByID(user_id_t block_id) {
113061da546Spatrick if (block_id == GetID())
114061da546Spatrick return this;
115061da546Spatrick
116061da546Spatrick Block *matching_block = nullptr;
117061da546Spatrick collection::const_iterator pos, end = m_children.end();
118061da546Spatrick for (pos = m_children.begin(); pos != end; ++pos) {
119061da546Spatrick matching_block = (*pos)->FindBlockByID(block_id);
120061da546Spatrick if (matching_block)
121061da546Spatrick break;
122061da546Spatrick }
123061da546Spatrick return matching_block;
124061da546Spatrick }
125061da546Spatrick
FindInnermostBlockByOffset(const lldb::addr_t offset)126*f6aab3d8Srobert Block *Block::FindInnermostBlockByOffset(const lldb::addr_t offset) {
127*f6aab3d8Srobert if (!Contains(offset))
128*f6aab3d8Srobert return nullptr;
129*f6aab3d8Srobert for (const BlockSP &block_sp : m_children) {
130*f6aab3d8Srobert if (Block *block = block_sp->FindInnermostBlockByOffset(offset))
131*f6aab3d8Srobert return block;
132*f6aab3d8Srobert }
133*f6aab3d8Srobert return this;
134*f6aab3d8Srobert }
135*f6aab3d8Srobert
CalculateSymbolContext(SymbolContext * sc)136061da546Spatrick void Block::CalculateSymbolContext(SymbolContext *sc) {
137061da546Spatrick if (m_parent_scope)
138061da546Spatrick m_parent_scope->CalculateSymbolContext(sc);
139061da546Spatrick sc->block = this;
140061da546Spatrick }
141061da546Spatrick
CalculateSymbolContextModule()142061da546Spatrick lldb::ModuleSP Block::CalculateSymbolContextModule() {
143061da546Spatrick if (m_parent_scope)
144061da546Spatrick return m_parent_scope->CalculateSymbolContextModule();
145061da546Spatrick return lldb::ModuleSP();
146061da546Spatrick }
147061da546Spatrick
CalculateSymbolContextCompileUnit()148061da546Spatrick CompileUnit *Block::CalculateSymbolContextCompileUnit() {
149061da546Spatrick if (m_parent_scope)
150061da546Spatrick return m_parent_scope->CalculateSymbolContextCompileUnit();
151061da546Spatrick return nullptr;
152061da546Spatrick }
153061da546Spatrick
CalculateSymbolContextFunction()154061da546Spatrick Function *Block::CalculateSymbolContextFunction() {
155061da546Spatrick if (m_parent_scope)
156061da546Spatrick return m_parent_scope->CalculateSymbolContextFunction();
157061da546Spatrick return nullptr;
158061da546Spatrick }
159061da546Spatrick
CalculateSymbolContextBlock()160061da546Spatrick Block *Block::CalculateSymbolContextBlock() { return this; }
161061da546Spatrick
DumpSymbolContext(Stream * s)162061da546Spatrick void Block::DumpSymbolContext(Stream *s) {
163061da546Spatrick Function *function = CalculateSymbolContextFunction();
164061da546Spatrick if (function)
165061da546Spatrick function->DumpSymbolContext(s);
166061da546Spatrick s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());
167061da546Spatrick }
168061da546Spatrick
DumpAddressRanges(Stream * s,lldb::addr_t base_addr)169061da546Spatrick void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) {
170061da546Spatrick if (!m_ranges.IsEmpty()) {
171061da546Spatrick size_t num_ranges = m_ranges.GetSize();
172061da546Spatrick for (size_t i = 0; i < num_ranges; ++i) {
173061da546Spatrick const Range &range = m_ranges.GetEntryRef(i);
174061da546Spatrick DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
175061da546Spatrick base_addr + range.GetRangeEnd(), 4);
176061da546Spatrick }
177061da546Spatrick }
178061da546Spatrick }
179061da546Spatrick
Contains(addr_t range_offset) const180061da546Spatrick bool Block::Contains(addr_t range_offset) const {
181061da546Spatrick return m_ranges.FindEntryThatContains(range_offset) != nullptr;
182061da546Spatrick }
183061da546Spatrick
Contains(const Block * block) const184061da546Spatrick bool Block::Contains(const Block *block) const {
185061da546Spatrick if (this == block)
186061da546Spatrick return false; // This block doesn't contain itself...
187061da546Spatrick
188061da546Spatrick // Walk the parent chain for "block" and see if any if them match this block
189061da546Spatrick const Block *block_parent;
190061da546Spatrick for (block_parent = block->GetParent(); block_parent != nullptr;
191061da546Spatrick block_parent = block_parent->GetParent()) {
192061da546Spatrick if (this == block_parent)
193061da546Spatrick return true; // One of the parents of "block" is this object!
194061da546Spatrick }
195061da546Spatrick return false;
196061da546Spatrick }
197061da546Spatrick
Contains(const Range & range) const198061da546Spatrick bool Block::Contains(const Range &range) const {
199061da546Spatrick return m_ranges.FindEntryThatContains(range) != nullptr;
200061da546Spatrick }
201061da546Spatrick
GetParent() const202061da546Spatrick Block *Block::GetParent() const {
203061da546Spatrick if (m_parent_scope)
204061da546Spatrick return m_parent_scope->CalculateSymbolContextBlock();
205061da546Spatrick return nullptr;
206061da546Spatrick }
207061da546Spatrick
GetContainingInlinedBlock()208061da546Spatrick Block *Block::GetContainingInlinedBlock() {
209061da546Spatrick if (GetInlinedFunctionInfo())
210061da546Spatrick return this;
211061da546Spatrick return GetInlinedParent();
212061da546Spatrick }
213061da546Spatrick
GetInlinedParent()214061da546Spatrick Block *Block::GetInlinedParent() {
215061da546Spatrick Block *parent_block = GetParent();
216061da546Spatrick if (parent_block) {
217061da546Spatrick if (parent_block->GetInlinedFunctionInfo())
218061da546Spatrick return parent_block;
219061da546Spatrick else
220061da546Spatrick return parent_block->GetInlinedParent();
221061da546Spatrick }
222061da546Spatrick return nullptr;
223061da546Spatrick }
224061da546Spatrick
GetContainingInlinedBlockWithCallSite(const Declaration & find_call_site)225061da546Spatrick Block *Block::GetContainingInlinedBlockWithCallSite(
226061da546Spatrick const Declaration &find_call_site) {
227061da546Spatrick Block *inlined_block = GetContainingInlinedBlock();
228061da546Spatrick
229061da546Spatrick while (inlined_block) {
230061da546Spatrick const auto *function_info = inlined_block->GetInlinedFunctionInfo();
231061da546Spatrick
232061da546Spatrick if (function_info &&
233061da546Spatrick function_info->GetCallSite().FileAndLineEqual(find_call_site))
234061da546Spatrick return inlined_block;
235061da546Spatrick inlined_block = inlined_block->GetInlinedParent();
236061da546Spatrick }
237061da546Spatrick return nullptr;
238061da546Spatrick }
239061da546Spatrick
GetRangeContainingOffset(const addr_t offset,Range & range)240061da546Spatrick bool Block::GetRangeContainingOffset(const addr_t offset, Range &range) {
241061da546Spatrick const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
242061da546Spatrick if (range_ptr) {
243061da546Spatrick range = *range_ptr;
244061da546Spatrick return true;
245061da546Spatrick }
246061da546Spatrick range.Clear();
247061da546Spatrick return false;
248061da546Spatrick }
249061da546Spatrick
GetRangeContainingAddress(const Address & addr,AddressRange & range)250061da546Spatrick bool Block::GetRangeContainingAddress(const Address &addr,
251061da546Spatrick AddressRange &range) {
252061da546Spatrick Function *function = CalculateSymbolContextFunction();
253061da546Spatrick if (function) {
254061da546Spatrick const AddressRange &func_range = function->GetAddressRange();
255061da546Spatrick if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
256061da546Spatrick const addr_t addr_offset = addr.GetOffset();
257061da546Spatrick const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
258061da546Spatrick if (addr_offset >= func_offset &&
259061da546Spatrick addr_offset < func_offset + func_range.GetByteSize()) {
260061da546Spatrick addr_t offset = addr_offset - func_offset;
261061da546Spatrick
262061da546Spatrick const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
263061da546Spatrick
264061da546Spatrick if (range_ptr) {
265061da546Spatrick range.GetBaseAddress() = func_range.GetBaseAddress();
266061da546Spatrick range.GetBaseAddress().SetOffset(func_offset +
267061da546Spatrick range_ptr->GetRangeBase());
268061da546Spatrick range.SetByteSize(range_ptr->GetByteSize());
269061da546Spatrick return true;
270061da546Spatrick }
271061da546Spatrick }
272061da546Spatrick }
273061da546Spatrick }
274061da546Spatrick range.Clear();
275061da546Spatrick return false;
276061da546Spatrick }
277061da546Spatrick
GetRangeContainingLoadAddress(lldb::addr_t load_addr,Target & target,AddressRange & range)278061da546Spatrick bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,
279061da546Spatrick Target &target, AddressRange &range) {
280061da546Spatrick Address load_address;
281061da546Spatrick load_address.SetLoadAddress(load_addr, &target);
282061da546Spatrick AddressRange containing_range;
283061da546Spatrick return GetRangeContainingAddress(load_address, containing_range);
284061da546Spatrick }
285061da546Spatrick
GetRangeIndexContainingAddress(const Address & addr)286061da546Spatrick uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
287061da546Spatrick Function *function = CalculateSymbolContextFunction();
288061da546Spatrick if (function) {
289061da546Spatrick const AddressRange &func_range = function->GetAddressRange();
290061da546Spatrick if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
291061da546Spatrick const addr_t addr_offset = addr.GetOffset();
292061da546Spatrick const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
293061da546Spatrick if (addr_offset >= func_offset &&
294061da546Spatrick addr_offset < func_offset + func_range.GetByteSize()) {
295061da546Spatrick addr_t offset = addr_offset - func_offset;
296061da546Spatrick return m_ranges.FindEntryIndexThatContains(offset);
297061da546Spatrick }
298061da546Spatrick }
299061da546Spatrick }
300061da546Spatrick return UINT32_MAX;
301061da546Spatrick }
302061da546Spatrick
GetRangeAtIndex(uint32_t range_idx,AddressRange & range)303061da546Spatrick bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
304061da546Spatrick if (range_idx < m_ranges.GetSize()) {
305061da546Spatrick Function *function = CalculateSymbolContextFunction();
306061da546Spatrick if (function) {
307061da546Spatrick const Range &vm_range = m_ranges.GetEntryRef(range_idx);
308061da546Spatrick range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
309061da546Spatrick range.GetBaseAddress().Slide(vm_range.GetRangeBase());
310061da546Spatrick range.SetByteSize(vm_range.GetByteSize());
311061da546Spatrick return true;
312061da546Spatrick }
313061da546Spatrick }
314061da546Spatrick return false;
315061da546Spatrick }
316061da546Spatrick
GetStartAddress(Address & addr)317061da546Spatrick bool Block::GetStartAddress(Address &addr) {
318061da546Spatrick if (m_ranges.IsEmpty())
319061da546Spatrick return false;
320061da546Spatrick
321061da546Spatrick Function *function = CalculateSymbolContextFunction();
322061da546Spatrick if (function) {
323061da546Spatrick addr = function->GetAddressRange().GetBaseAddress();
324061da546Spatrick addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase());
325061da546Spatrick return true;
326061da546Spatrick }
327061da546Spatrick return false;
328061da546Spatrick }
329061da546Spatrick
FinalizeRanges()330061da546Spatrick void Block::FinalizeRanges() {
331061da546Spatrick m_ranges.Sort();
332061da546Spatrick m_ranges.CombineConsecutiveRanges();
333061da546Spatrick }
334061da546Spatrick
AddRange(const Range & range)335061da546Spatrick void Block::AddRange(const Range &range) {
336061da546Spatrick Block *parent_block = GetParent();
337061da546Spatrick if (parent_block && !parent_block->Contains(range)) {
338*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Symbols);
339061da546Spatrick if (log) {
340061da546Spatrick ModuleSP module_sp(m_parent_scope->CalculateSymbolContextModule());
341061da546Spatrick Function *function = m_parent_scope->CalculateSymbolContextFunction();
342061da546Spatrick const addr_t function_file_addr =
343061da546Spatrick function->GetAddressRange().GetBaseAddress().GetFileAddress();
344061da546Spatrick const addr_t block_start_addr = function_file_addr + range.GetRangeBase();
345061da546Spatrick const addr_t block_end_addr = function_file_addr + range.GetRangeEnd();
346061da546Spatrick Type *func_type = function->GetType();
347061da546Spatrick
348061da546Spatrick const Declaration &func_decl = func_type->GetDeclaration();
349061da546Spatrick if (func_decl.GetLine()) {
350061da546Spatrick LLDB_LOGF(log,
351061da546Spatrick "warning: %s:%u block {0x%8.8" PRIx64
352061da546Spatrick "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64
353061da546Spatrick ") which is not contained in parent block {0x%8.8" PRIx64
354061da546Spatrick "} in function {0x%8.8" PRIx64 "} from %s",
355061da546Spatrick func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(),
356061da546Spatrick GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
357061da546Spatrick block_end_addr, parent_block->GetID(), function->GetID(),
358061da546Spatrick module_sp->GetFileSpec().GetPath().c_str());
359061da546Spatrick } else {
360061da546Spatrick LLDB_LOGF(log,
361061da546Spatrick "warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64
362061da546Spatrick " - 0x%" PRIx64
363061da546Spatrick ") which is not contained in parent block {0x%8.8" PRIx64
364061da546Spatrick "} in function {0x%8.8" PRIx64 "} from %s",
365061da546Spatrick GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
366061da546Spatrick block_end_addr, parent_block->GetID(), function->GetID(),
367061da546Spatrick module_sp->GetFileSpec().GetPath().c_str());
368061da546Spatrick }
369061da546Spatrick }
370061da546Spatrick parent_block->AddRange(range);
371061da546Spatrick }
372061da546Spatrick m_ranges.Append(range);
373061da546Spatrick }
374061da546Spatrick
375061da546Spatrick // Return the current number of bytes that this object occupies in memory
MemorySize() const376061da546Spatrick size_t Block::MemorySize() const {
377061da546Spatrick size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);
378061da546Spatrick if (m_inlineInfoSP.get())
379061da546Spatrick mem_size += m_inlineInfoSP->MemorySize();
380061da546Spatrick if (m_variable_list_sp.get())
381061da546Spatrick mem_size += m_variable_list_sp->MemorySize();
382061da546Spatrick return mem_size;
383061da546Spatrick }
384061da546Spatrick
AddChild(const BlockSP & child_block_sp)385061da546Spatrick void Block::AddChild(const BlockSP &child_block_sp) {
386061da546Spatrick if (child_block_sp) {
387061da546Spatrick child_block_sp->SetParentScope(this);
388061da546Spatrick m_children.push_back(child_block_sp);
389061da546Spatrick }
390061da546Spatrick }
391061da546Spatrick
SetInlinedFunctionInfo(const char * name,const char * mangled,const Declaration * decl_ptr,const Declaration * call_decl_ptr)392061da546Spatrick void Block::SetInlinedFunctionInfo(const char *name, const char *mangled,
393061da546Spatrick const Declaration *decl_ptr,
394061da546Spatrick const Declaration *call_decl_ptr) {
395061da546Spatrick m_inlineInfoSP = std::make_shared<InlineFunctionInfo>(name, mangled, decl_ptr,
396061da546Spatrick call_decl_ptr);
397061da546Spatrick }
398061da546Spatrick
GetBlockVariableList(bool can_create)399061da546Spatrick VariableListSP Block::GetBlockVariableList(bool can_create) {
400061da546Spatrick if (!m_parsed_block_variables) {
401061da546Spatrick if (m_variable_list_sp.get() == nullptr && can_create) {
402061da546Spatrick m_parsed_block_variables = true;
403061da546Spatrick SymbolContext sc;
404061da546Spatrick CalculateSymbolContext(&sc);
405061da546Spatrick assert(sc.module_sp);
406061da546Spatrick sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc);
407061da546Spatrick }
408061da546Spatrick }
409061da546Spatrick return m_variable_list_sp;
410061da546Spatrick }
411061da546Spatrick
412061da546Spatrick uint32_t
AppendBlockVariables(bool can_create,bool get_child_block_variables,bool stop_if_child_block_is_inlined_function,const std::function<bool (Variable *)> & filter,VariableList * variable_list)413061da546Spatrick Block::AppendBlockVariables(bool can_create, bool get_child_block_variables,
414061da546Spatrick bool stop_if_child_block_is_inlined_function,
415061da546Spatrick const std::function<bool(Variable *)> &filter,
416061da546Spatrick VariableList *variable_list) {
417061da546Spatrick uint32_t num_variables_added = 0;
418061da546Spatrick VariableList *block_var_list = GetBlockVariableList(can_create).get();
419061da546Spatrick if (block_var_list) {
420061da546Spatrick for (const VariableSP &var_sp : *block_var_list) {
421061da546Spatrick if (filter(var_sp.get())) {
422061da546Spatrick num_variables_added++;
423061da546Spatrick variable_list->AddVariable(var_sp);
424061da546Spatrick }
425061da546Spatrick }
426061da546Spatrick }
427061da546Spatrick
428061da546Spatrick if (get_child_block_variables) {
429061da546Spatrick collection::const_iterator pos, end = m_children.end();
430061da546Spatrick for (pos = m_children.begin(); pos != end; ++pos) {
431061da546Spatrick Block *child_block = pos->get();
432061da546Spatrick if (!stop_if_child_block_is_inlined_function ||
433061da546Spatrick child_block->GetInlinedFunctionInfo() == nullptr) {
434061da546Spatrick num_variables_added += child_block->AppendBlockVariables(
435061da546Spatrick can_create, get_child_block_variables,
436061da546Spatrick stop_if_child_block_is_inlined_function, filter, variable_list);
437061da546Spatrick }
438061da546Spatrick }
439061da546Spatrick }
440061da546Spatrick return num_variables_added;
441061da546Spatrick }
442061da546Spatrick
AppendVariables(bool can_create,bool get_parent_variables,bool stop_if_block_is_inlined_function,const std::function<bool (Variable *)> & filter,VariableList * variable_list)443061da546Spatrick uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables,
444061da546Spatrick bool stop_if_block_is_inlined_function,
445061da546Spatrick const std::function<bool(Variable *)> &filter,
446061da546Spatrick VariableList *variable_list) {
447061da546Spatrick uint32_t num_variables_added = 0;
448061da546Spatrick VariableListSP variable_list_sp(GetBlockVariableList(can_create));
449061da546Spatrick
450061da546Spatrick bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;
451061da546Spatrick if (variable_list_sp) {
452061da546Spatrick for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) {
453061da546Spatrick VariableSP variable = variable_list_sp->GetVariableAtIndex(i);
454061da546Spatrick if (filter(variable.get())) {
455061da546Spatrick num_variables_added++;
456061da546Spatrick variable_list->AddVariable(variable);
457061da546Spatrick }
458061da546Spatrick }
459061da546Spatrick }
460061da546Spatrick
461061da546Spatrick if (get_parent_variables) {
462061da546Spatrick if (stop_if_block_is_inlined_function && is_inlined_function)
463061da546Spatrick return num_variables_added;
464061da546Spatrick
465061da546Spatrick Block *parent_block = GetParent();
466061da546Spatrick if (parent_block)
467061da546Spatrick num_variables_added += parent_block->AppendVariables(
468061da546Spatrick can_create, get_parent_variables, stop_if_block_is_inlined_function,
469061da546Spatrick filter, variable_list);
470061da546Spatrick }
471061da546Spatrick return num_variables_added;
472061da546Spatrick }
473061da546Spatrick
GetSymbolFile()474061da546Spatrick SymbolFile *Block::GetSymbolFile() {
475061da546Spatrick if (ModuleSP module_sp = CalculateSymbolContextModule())
476061da546Spatrick return module_sp->GetSymbolFile();
477061da546Spatrick return nullptr;
478061da546Spatrick }
479061da546Spatrick
GetDeclContext()480061da546Spatrick CompilerDeclContext Block::GetDeclContext() {
481061da546Spatrick if (SymbolFile *sym_file = GetSymbolFile())
482061da546Spatrick return sym_file->GetDeclContextForUID(GetID());
483061da546Spatrick return CompilerDeclContext();
484061da546Spatrick }
485061da546Spatrick
SetBlockInfoHasBeenParsed(bool b,bool set_children)486061da546Spatrick void Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) {
487061da546Spatrick m_parsed_block_info = b;
488061da546Spatrick if (set_children) {
489061da546Spatrick m_parsed_child_blocks = true;
490061da546Spatrick collection::const_iterator pos, end = m_children.end();
491061da546Spatrick for (pos = m_children.begin(); pos != end; ++pos)
492061da546Spatrick (*pos)->SetBlockInfoHasBeenParsed(b, true);
493061da546Spatrick }
494061da546Spatrick }
495061da546Spatrick
SetDidParseVariables(bool b,bool set_children)496061da546Spatrick void Block::SetDidParseVariables(bool b, bool set_children) {
497061da546Spatrick m_parsed_block_variables = b;
498061da546Spatrick if (set_children) {
499061da546Spatrick collection::const_iterator pos, end = m_children.end();
500061da546Spatrick for (pos = m_children.begin(); pos != end; ++pos)
501061da546Spatrick (*pos)->SetDidParseVariables(b, true);
502061da546Spatrick }
503061da546Spatrick }
504061da546Spatrick
GetSibling() const505061da546Spatrick Block *Block::GetSibling() const {
506061da546Spatrick if (m_parent_scope) {
507061da546Spatrick Block *parent_block = GetParent();
508061da546Spatrick if (parent_block)
509061da546Spatrick return parent_block->GetSiblingForChild(this);
510061da546Spatrick }
511061da546Spatrick return nullptr;
512061da546Spatrick }
513061da546Spatrick // A parent of child blocks can be asked to find a sibling block given
514061da546Spatrick // one of its child blocks
GetSiblingForChild(const Block * child_block) const515061da546Spatrick Block *Block::GetSiblingForChild(const Block *child_block) const {
516061da546Spatrick if (!m_children.empty()) {
517061da546Spatrick collection::const_iterator pos, end = m_children.end();
518061da546Spatrick for (pos = m_children.begin(); pos != end; ++pos) {
519061da546Spatrick if (pos->get() == child_block) {
520061da546Spatrick if (++pos != end)
521061da546Spatrick return pos->get();
522061da546Spatrick break;
523061da546Spatrick }
524061da546Spatrick }
525061da546Spatrick }
526061da546Spatrick return nullptr;
527061da546Spatrick }
528