Variable.cpp revision 296417
1254721Semaste//===-- Variable.cpp --------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Symbol/Variable.h"
11254721Semaste
12254721Semaste#include "lldb/Core/Module.h"
13254721Semaste#include "lldb/Core/Stream.h"
14254721Semaste#include "lldb/Core/RegularExpression.h"
15254721Semaste#include "lldb/Core/ValueObject.h"
16254721Semaste#include "lldb/Core/ValueObjectVariable.h"
17254721Semaste#include "lldb/Symbol/Block.h"
18296417Sdim#include "lldb/Symbol/CompilerDecl.h"
19296417Sdim#include "lldb/Symbol/CompilerDeclContext.h"
20288943Sdim#include "lldb/Symbol/CompileUnit.h"
21254721Semaste#include "lldb/Symbol/Function.h"
22254721Semaste#include "lldb/Symbol/SymbolContext.h"
23296417Sdim#include "lldb/Symbol/SymbolFile.h"
24254721Semaste#include "lldb/Symbol/Type.h"
25296417Sdim#include "lldb/Symbol/TypeSystem.h"
26254721Semaste#include "lldb/Symbol/VariableList.h"
27254721Semaste#include "lldb/Target/ABI.h"
28254721Semaste#include "lldb/Target/Process.h"
29254721Semaste#include "lldb/Target/RegisterContext.h"
30254721Semaste#include "lldb/Target/StackFrame.h"
31254721Semaste#include "lldb/Target/Thread.h"
32254721Semaste#include "lldb/Target/Target.h"
33254721Semaste
34254721Semasteusing namespace lldb;
35254721Semasteusing namespace lldb_private;
36254721Semaste
37254721Semaste//----------------------------------------------------------------------
38254721Semaste// Variable constructor
39254721Semaste//----------------------------------------------------------------------
40296417SdimVariable::Variable (lldb::user_id_t uid,
41296417Sdim                    const char *name,
42296417Sdim                    const char *mangled,  // The mangled or fully qualified name of the variable.
43296417Sdim                    const lldb::SymbolFileTypeSP &symfile_type_sp,
44296417Sdim                    ValueType scope,
45296417Sdim                    SymbolContextScope *context,
46296417Sdim                    Declaration* decl_ptr,
47296417Sdim                    const DWARFExpression& location,
48296417Sdim                    bool external,
49296417Sdim                    bool artificial,
50296417Sdim                    bool static_member) :
51254721Semaste    UserID(uid),
52254721Semaste    m_name(name),
53288943Sdim    m_mangled (ConstString(mangled)),
54254721Semaste    m_symfile_type_sp(symfile_type_sp),
55254721Semaste    m_scope(scope),
56254721Semaste    m_owner_scope(context),
57254721Semaste    m_declaration(decl_ptr),
58254721Semaste    m_location(location),
59254721Semaste    m_external(external),
60296417Sdim    m_artificial(artificial),
61296417Sdim    m_static_member(static_member)
62254721Semaste{
63254721Semaste}
64254721Semaste
65254721Semaste//----------------------------------------------------------------------
66254721Semaste// Destructor
67254721Semaste//----------------------------------------------------------------------
68254721SemasteVariable::~Variable()
69254721Semaste{
70254721Semaste}
71254721Semaste
72288943Sdimlldb::LanguageType
73288943SdimVariable::GetLanguage () const
74288943Sdim{
75288943Sdim    SymbolContext variable_sc;
76288943Sdim    m_owner_scope->CalculateSymbolContext(&variable_sc);
77288943Sdim    if (variable_sc.comp_unit)
78288943Sdim        return variable_sc.comp_unit->GetLanguage();
79288943Sdim    return lldb::eLanguageTypeUnknown;
80288943Sdim}
81254721Semaste
82288943Sdim
83288943Sdim
84288943SdimConstString
85254721SemasteVariable::GetName() const
86254721Semaste{
87288943Sdim    ConstString name = m_mangled.GetName(GetLanguage());
88288943Sdim    if (name)
89288943Sdim        return name;
90254721Semaste    return m_name;
91254721Semaste}
92254721Semaste
93296417SdimConstString
94296417SdimVariable::GetUnqualifiedName() const
95296417Sdim{
96296417Sdim    return m_name;
97296417Sdim}
98296417Sdim
99296417Sdim
100254721Semastebool
101288943SdimVariable::NameMatches (const ConstString &name) const
102288943Sdim{
103288943Sdim    if (m_name == name)
104288943Sdim        return true;
105288943Sdim    SymbolContext variable_sc;
106288943Sdim    m_owner_scope->CalculateSymbolContext(&variable_sc);
107288943Sdim
108288943Sdim    LanguageType language = eLanguageTypeUnknown;
109288943Sdim    if (variable_sc.comp_unit)
110288943Sdim        language = variable_sc.comp_unit->GetLanguage();
111288943Sdim    return m_mangled.NameMatches (name, language);
112288943Sdim}
113288943Sdimbool
114254721SemasteVariable::NameMatches (const RegularExpression& regex) const
115254721Semaste{
116254721Semaste    if (regex.Execute (m_name.AsCString()))
117254721Semaste        return true;
118288943Sdim    if (m_mangled)
119288943Sdim        return m_mangled.NameMatches (regex, GetLanguage());
120288943Sdim    return false;
121254721Semaste}
122254721Semaste
123254721SemasteType *
124254721SemasteVariable::GetType()
125254721Semaste{
126254721Semaste    if (m_symfile_type_sp)
127254721Semaste        return m_symfile_type_sp->GetType();
128276479Sdim    return nullptr;
129254721Semaste}
130254721Semaste
131254721Semastevoid
132254721SemasteVariable::Dump(Stream *s, bool show_context) const
133254721Semaste{
134276479Sdim    s->Printf("%p: ", static_cast<const void*>(this));
135254721Semaste    s->Indent();
136254721Semaste    *s << "Variable" << (const UserID&)*this;
137254721Semaste
138254721Semaste    if (m_name)
139254721Semaste        *s << ", name = \"" << m_name << "\"";
140254721Semaste
141254721Semaste    if (m_symfile_type_sp)
142254721Semaste    {
143254721Semaste        Type *type = m_symfile_type_sp->GetType();
144254721Semaste        if (type)
145254721Semaste        {
146254721Semaste            *s << ", type = {" << type->GetID() << "} " << (void*)type << " (";
147254721Semaste            type->DumpTypeName(s);
148254721Semaste            s->PutChar(')');
149254721Semaste        }
150254721Semaste    }
151254721Semaste
152254721Semaste    if (m_scope != eValueTypeInvalid)
153254721Semaste    {
154254721Semaste        s->PutCString(", scope = ");
155254721Semaste        switch (m_scope)
156254721Semaste        {
157254721Semaste        case eValueTypeVariableGlobal:       s->PutCString(m_external ? "global" : "static"); break;
158254721Semaste        case eValueTypeVariableArgument:    s->PutCString("parameter"); break;
159254721Semaste        case eValueTypeVariableLocal:        s->PutCString("local"); break;
160254721Semaste        default:            *s << "??? (" << m_scope << ')';
161254721Semaste        }
162254721Semaste    }
163254721Semaste
164276479Sdim    if (show_context && m_owner_scope != nullptr)
165254721Semaste    {
166254721Semaste        s->PutCString(", context = ( ");
167254721Semaste        m_owner_scope->DumpSymbolContext(s);
168254721Semaste        s->PutCString(" )");
169254721Semaste    }
170254721Semaste
171254721Semaste    bool show_fullpaths = false;
172254721Semaste    m_declaration.Dump(s, show_fullpaths);
173254721Semaste
174254721Semaste    if (m_location.IsValid())
175254721Semaste    {
176254721Semaste        s->PutCString(", location = ");
177254721Semaste        lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
178254721Semaste        if (m_location.IsLocationList())
179254721Semaste        {
180254721Semaste            SymbolContext variable_sc;
181254721Semaste            m_owner_scope->CalculateSymbolContext(&variable_sc);
182254721Semaste            if (variable_sc.function)
183254721Semaste                loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
184254721Semaste        }
185276479Sdim        ABI *abi = nullptr;
186254721Semaste        if (m_owner_scope)
187254721Semaste        {
188254721Semaste            ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule());
189254721Semaste            if (module_sp)
190254721Semaste                abi = ABI::FindPlugin (module_sp->GetArchitecture()).get();
191254721Semaste        }
192254721Semaste        m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr, abi);
193254721Semaste    }
194254721Semaste
195254721Semaste    if (m_external)
196254721Semaste        s->PutCString(", external");
197254721Semaste
198254721Semaste    if (m_artificial)
199254721Semaste        s->PutCString(", artificial");
200254721Semaste
201254721Semaste    s->EOL();
202254721Semaste}
203254721Semaste
204254721Semastebool
205254721SemasteVariable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module)
206254721Semaste{
207254721Semaste    bool dumped_declaration_info = false;
208254721Semaste    if (m_owner_scope)
209254721Semaste    {
210254721Semaste        SymbolContext sc;
211254721Semaste        m_owner_scope->CalculateSymbolContext(&sc);
212276479Sdim        sc.block = nullptr;
213254721Semaste        sc.line_entry.Clear();
214254721Semaste        bool show_inlined_frames = false;
215280031Sdim        const bool show_function_arguments = true;
216288943Sdim        const bool show_function_name = true;
217254721Semaste
218254721Semaste        dumped_declaration_info = sc.DumpStopContext (s,
219276479Sdim                                                      nullptr,
220254721Semaste                                                      Address(),
221254721Semaste                                                      show_fullpaths,
222254721Semaste                                                      show_module,
223280031Sdim                                                      show_inlined_frames,
224288943Sdim                                                      show_function_arguments,
225288943Sdim                                                      show_function_name);
226254721Semaste
227254721Semaste        if (sc.function)
228254721Semaste            s->PutChar(':');
229254721Semaste    }
230254721Semaste    if (m_declaration.DumpStopContext (s, false))
231254721Semaste        dumped_declaration_info = true;
232254721Semaste    return dumped_declaration_info;
233254721Semaste}
234254721Semaste
235254721Semastesize_t
236254721SemasteVariable::MemorySize() const
237254721Semaste{
238254721Semaste    return sizeof(Variable);
239254721Semaste}
240254721Semaste
241296417SdimCompilerDeclContext
242296417SdimVariable::GetDeclContext ()
243296417Sdim{
244296417Sdim    Type *type = GetType();
245296417Sdim    return type->GetSymbolFile()->GetDeclContextContainingUID(GetID());
246296417Sdim}
247254721Semaste
248296417SdimCompilerDecl
249296417SdimVariable::GetDecl ()
250296417Sdim{
251296417Sdim    Type *type = GetType();
252296417Sdim    CompilerDecl decl = type->GetSymbolFile()->GetDeclForUID(GetID());
253296417Sdim    if (decl)
254296417Sdim        decl.GetTypeSystem()->DeclLinkToObject(decl.GetOpaqueDecl(), shared_from_this());
255296417Sdim    return decl;
256296417Sdim}
257296417Sdim
258254721Semastevoid
259254721SemasteVariable::CalculateSymbolContext (SymbolContext *sc)
260254721Semaste{
261254721Semaste    if (m_owner_scope)
262288943Sdim    {
263254721Semaste        m_owner_scope->CalculateSymbolContext(sc);
264288943Sdim        sc->variable = this;
265288943Sdim    }
266254721Semaste    else
267254721Semaste        sc->Clear(false);
268254721Semaste}
269254721Semaste
270254721Semastebool
271254721SemasteVariable::LocationIsValidForFrame (StackFrame *frame)
272254721Semaste{
273254721Semaste    // Is the variable is described by a single location?
274254721Semaste    if (!m_location.IsLocationList())
275254721Semaste    {
276254721Semaste        // Yes it is, the location is valid.
277254721Semaste        return true;
278254721Semaste    }
279254721Semaste
280254721Semaste    if (frame)
281254721Semaste    {
282254721Semaste        Function *function = frame->GetSymbolContext(eSymbolContextFunction).function;
283254721Semaste        if (function)
284254721Semaste        {
285254721Semaste            TargetSP target_sp (frame->CalculateTarget());
286254721Semaste
287254721Semaste            addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target_sp.get());
288254721Semaste            if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
289254721Semaste                return false;
290254721Semaste            // It is a location list. We just need to tell if the location
291254721Semaste            // list contains the current address when converted to a load
292254721Semaste            // address
293254721Semaste            return m_location.LocationListContainsAddress (loclist_base_load_addr,
294254721Semaste                                                           frame->GetFrameCodeAddress().GetLoadAddress (target_sp.get()));
295254721Semaste        }
296254721Semaste    }
297254721Semaste    return false;
298254721Semaste}
299254721Semaste
300254721Semastebool
301254721SemasteVariable::LocationIsValidForAddress (const Address &address)
302254721Semaste{
303254721Semaste    // Be sure to resolve the address to section offset prior to
304254721Semaste    // calling this function.
305254721Semaste    if (address.IsSectionOffset())
306254721Semaste    {
307254721Semaste        SymbolContext sc;
308254721Semaste        CalculateSymbolContext(&sc);
309254721Semaste        if (sc.module_sp == address.GetModule())
310254721Semaste        {
311254721Semaste            // Is the variable is described by a single location?
312254721Semaste            if (!m_location.IsLocationList())
313254721Semaste            {
314254721Semaste                // Yes it is, the location is valid.
315254721Semaste                return true;
316254721Semaste            }
317254721Semaste
318254721Semaste            if (sc.function)
319254721Semaste            {
320254721Semaste                addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
321254721Semaste                if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
322254721Semaste                    return false;
323254721Semaste                // It is a location list. We just need to tell if the location
324254721Semaste                // list contains the current address when converted to a load
325254721Semaste                // address
326254721Semaste                return m_location.LocationListContainsAddress (loclist_base_file_addr,
327254721Semaste                                                               address.GetFileAddress());
328254721Semaste            }
329254721Semaste        }
330254721Semaste    }
331254721Semaste    return false;
332254721Semaste}
333254721Semaste
334254721Semastebool
335254721SemasteVariable::IsInScope (StackFrame *frame)
336254721Semaste{
337254721Semaste    switch (m_scope)
338254721Semaste    {
339254721Semaste    case eValueTypeRegister:
340254721Semaste    case eValueTypeRegisterSet:
341276479Sdim        return frame != nullptr;
342254721Semaste
343254721Semaste    case eValueTypeConstResult:
344254721Semaste    case eValueTypeVariableGlobal:
345254721Semaste    case eValueTypeVariableStatic:
346254721Semaste        return true;
347254721Semaste
348254721Semaste    case eValueTypeVariableArgument:
349254721Semaste    case eValueTypeVariableLocal:
350254721Semaste        if (frame)
351254721Semaste        {
352254721Semaste            // We don't have a location list, we just need to see if the block
353254721Semaste            // that this variable was defined in is currently
354254721Semaste            Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
355254721Semaste            if (deepest_frame_block)
356254721Semaste            {
357254721Semaste                SymbolContext variable_sc;
358254721Semaste                CalculateSymbolContext (&variable_sc);
359254721Semaste                // Check for static or global variable defined at the compile unit
360254721Semaste                // level that wasn't defined in a block
361276479Sdim                if (variable_sc.block == nullptr)
362254721Semaste                    return true;
363254721Semaste
364254721Semaste                if (variable_sc.block == deepest_frame_block)
365254721Semaste                    return true;
366254721Semaste                return variable_sc.block->Contains (deepest_frame_block);
367254721Semaste            }
368254721Semaste        }
369254721Semaste        break;
370254721Semaste
371254721Semaste    default:
372254721Semaste        break;
373254721Semaste    }
374254721Semaste    return false;
375254721Semaste}
376254721Semaste
377254721SemasteError
378254721SemasteVariable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
379254721Semaste                                              ExecutionContextScope *scope,
380254721Semaste                                              GetVariableCallback callback,
381254721Semaste                                              void *baton,
382254721Semaste                                              VariableList &variable_list,
383254721Semaste                                              ValueObjectList &valobj_list)
384254721Semaste{
385254721Semaste    Error error;
386254721Semaste    if (variable_expr_path && callback)
387254721Semaste    {
388254721Semaste        switch (variable_expr_path[0])
389254721Semaste        {
390254721Semaste        case '*':
391254721Semaste            {
392254721Semaste                error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
393254721Semaste                                                                      scope,
394254721Semaste                                                                      callback,
395254721Semaste                                                                      baton,
396254721Semaste                                                                      variable_list,
397254721Semaste                                                                      valobj_list);
398254721Semaste                if (error.Success())
399254721Semaste                {
400254721Semaste                    for (uint32_t i=0; i<valobj_list.GetSize(); )
401254721Semaste                    {
402254721Semaste                        Error tmp_error;
403254721Semaste                        ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error));
404254721Semaste                        if (tmp_error.Fail())
405254721Semaste                        {
406254721Semaste                            variable_list.RemoveVariableAtIndex (i);
407254721Semaste                            valobj_list.RemoveValueObjectAtIndex (i);
408254721Semaste                        }
409254721Semaste                        else
410254721Semaste                        {
411254721Semaste                            valobj_list.SetValueObjectAtIndex (i, valobj_sp);
412254721Semaste                            ++i;
413254721Semaste                        }
414254721Semaste                    }
415254721Semaste                }
416254721Semaste                else
417254721Semaste                {
418254721Semaste                    error.SetErrorString ("unknown error");
419254721Semaste                }
420254721Semaste                return error;
421254721Semaste            }
422254721Semaste            break;
423254721Semaste
424254721Semaste        case '&':
425254721Semaste            {
426254721Semaste                error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
427254721Semaste                                                                      scope,
428254721Semaste                                                                      callback,
429254721Semaste                                                                      baton,
430254721Semaste                                                                      variable_list,
431254721Semaste                                                                      valobj_list);
432254721Semaste                if (error.Success())
433254721Semaste                {
434254721Semaste                    for (uint32_t i=0; i<valobj_list.GetSize(); )
435254721Semaste                    {
436254721Semaste                        Error tmp_error;
437254721Semaste                        ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
438254721Semaste                        if (tmp_error.Fail())
439254721Semaste                        {
440254721Semaste                            variable_list.RemoveVariableAtIndex (i);
441254721Semaste                            valobj_list.RemoveValueObjectAtIndex (i);
442254721Semaste                        }
443254721Semaste                        else
444254721Semaste                        {
445254721Semaste                            valobj_list.SetValueObjectAtIndex (i, valobj_sp);
446254721Semaste                            ++i;
447254721Semaste                        }
448254721Semaste                    }
449254721Semaste                }
450254721Semaste                else
451254721Semaste                {
452254721Semaste                    error.SetErrorString ("unknown error");
453254721Semaste                }
454254721Semaste                return error;
455254721Semaste            }
456254721Semaste            break;
457254721Semaste
458254721Semaste        default:
459254721Semaste            {
460254721Semaste                static RegularExpression g_regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)");
461254721Semaste                RegularExpression::Match regex_match(1);
462254721Semaste                if (g_regex.Execute(variable_expr_path, &regex_match))
463254721Semaste                {
464254721Semaste                    std::string variable_name;
465254721Semaste                    if (regex_match.GetMatchAtIndex(variable_expr_path, 1, variable_name))
466254721Semaste                    {
467254721Semaste                        variable_list.Clear();
468254721Semaste                        if (callback (baton, variable_name.c_str(), variable_list))
469254721Semaste                        {
470254721Semaste                            uint32_t i=0;
471254721Semaste                            while (i < variable_list.GetSize())
472254721Semaste                            {
473254721Semaste                                VariableSP var_sp (variable_list.GetVariableAtIndex (i));
474254721Semaste                                ValueObjectSP valobj_sp;
475254721Semaste                                if (var_sp)
476254721Semaste                                {
477254721Semaste                                    ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
478254721Semaste                                    if (variable_valobj_sp)
479254721Semaste                                    {
480254721Semaste                                        const char *variable_sub_expr_path = variable_expr_path + variable_name.size();
481254721Semaste                                        if (*variable_sub_expr_path)
482254721Semaste                                        {
483276479Sdim                                            const char* first_unparsed = nullptr;
484254721Semaste                                            ValueObject::ExpressionPathScanEndReason reason_to_stop;
485254721Semaste                                            ValueObject::ExpressionPathEndResultType final_value_type;
486254721Semaste                                            ValueObject::GetValueForExpressionPathOptions options;
487254721Semaste                                            ValueObject::ExpressionPathAftermath final_task_on_target;
488254721Semaste
489254721Semaste                                            valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_sub_expr_path,
490254721Semaste                                                                                                       &first_unparsed,
491254721Semaste                                                                                                       &reason_to_stop,
492254721Semaste                                                                                                       &final_value_type,
493254721Semaste                                                                                                       options,
494254721Semaste                                                                                                       &final_task_on_target);
495254721Semaste                                            if (!valobj_sp)
496254721Semaste                                            {
497254721Semaste                                                error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
498254721Semaste                                                                                variable_sub_expr_path,
499254721Semaste                                                                                var_sp->GetName().GetCString());
500254721Semaste                                            }
501254721Semaste                                        }
502254721Semaste                                        else
503254721Semaste                                        {
504254721Semaste                                            // Just the name of a variable with no extras
505254721Semaste                                            valobj_sp = variable_valobj_sp;
506254721Semaste                                        }
507254721Semaste                                    }
508254721Semaste                                }
509254721Semaste
510254721Semaste                                if (!var_sp || !valobj_sp)
511254721Semaste                                {
512254721Semaste                                    variable_list.RemoveVariableAtIndex (i);
513254721Semaste                                }
514254721Semaste                                else
515254721Semaste                                {
516254721Semaste                                    valobj_list.Append(valobj_sp);
517254721Semaste                                    ++i;
518254721Semaste                                }
519254721Semaste                            }
520254721Semaste
521254721Semaste                            if (variable_list.GetSize() > 0)
522254721Semaste                            {
523254721Semaste                                error.Clear();
524254721Semaste                                return error;
525254721Semaste                            }
526254721Semaste                        }
527254721Semaste                    }
528254721Semaste                }
529254721Semaste                error.SetErrorStringWithFormat ("unable to extract a variable name from '%s'", variable_expr_path);
530254721Semaste            }
531254721Semaste            break;
532254721Semaste        }
533254721Semaste    }
534254721Semaste    error.SetErrorString ("unknown error");
535254721Semaste    return error;
536254721Semaste}
537254721Semaste
538254721Semastebool
539254721SemasteVariable::DumpLocationForAddress (Stream *s, const Address &address)
540254721Semaste{
541254721Semaste    // Be sure to resolve the address to section offset prior to
542254721Semaste    // calling this function.
543254721Semaste    if (address.IsSectionOffset())
544254721Semaste    {
545254721Semaste        SymbolContext sc;
546254721Semaste        CalculateSymbolContext(&sc);
547254721Semaste        if (sc.module_sp == address.GetModule())
548254721Semaste        {
549276479Sdim            ABI *abi = nullptr;
550254721Semaste            if (m_owner_scope)
551254721Semaste            {
552254721Semaste                ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule());
553254721Semaste                if (module_sp)
554254721Semaste                    abi = ABI::FindPlugin (module_sp->GetArchitecture()).get();
555254721Semaste            }
556254721Semaste
557254721Semaste            const addr_t file_addr = address.GetFileAddress();
558254721Semaste            if (sc.function)
559254721Semaste            {
560254721Semaste                if (sc.function->GetAddressRange().ContainsFileAddress(address))
561254721Semaste                {
562254721Semaste                    addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
563254721Semaste                    if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
564254721Semaste                        return false;
565254721Semaste                    return m_location.DumpLocationForAddress (s,
566254721Semaste                                                              eDescriptionLevelBrief,
567254721Semaste                                                              loclist_base_file_addr,
568254721Semaste                                                              file_addr,
569254721Semaste                                                              abi);
570254721Semaste                }
571254721Semaste            }
572254721Semaste            return m_location.DumpLocationForAddress (s,
573254721Semaste                                                      eDescriptionLevelBrief,
574254721Semaste                                                      LLDB_INVALID_ADDRESS,
575254721Semaste                                                      file_addr,
576254721Semaste                                                      abi);
577254721Semaste        }
578254721Semaste    }
579254721Semaste    return false;
580254721Semaste}
581254721Semaste
582254721Semaste
583254721Semastestatic void
584254721SemastePrivateAutoComplete (StackFrame *frame,
585254721Semaste                     const std::string &partial_path,
586254721Semaste                     const std::string &prefix_path, // Anything that has been resolved already will be in here
587296417Sdim                     const CompilerType& compiler_type,
588254721Semaste                     StringList &matches,
589254721Semaste                     bool &word_complete);
590254721Semaste
591254721Semastestatic void
592254721SemastePrivateAutoCompleteMembers (StackFrame *frame,
593254721Semaste                            const std::string &partial_member_name,
594254721Semaste                            const std::string &partial_path,
595254721Semaste                            const std::string &prefix_path, // Anything that has been resolved already will be in here
596296417Sdim                            const CompilerType& compiler_type,
597254721Semaste                            StringList &matches,
598254721Semaste                            bool &word_complete);
599254721Semaste
600254721Semastestatic void
601254721SemastePrivateAutoCompleteMembers (StackFrame *frame,
602254721Semaste                            const std::string &partial_member_name,
603254721Semaste                            const std::string &partial_path,
604254721Semaste                            const std::string &prefix_path, // Anything that has been resolved already will be in here
605296417Sdim                            const CompilerType& compiler_type,
606254721Semaste                            StringList &matches,
607254721Semaste                            bool &word_complete)
608254721Semaste{
609254721Semaste
610254721Semaste    // We are in a type parsing child members
611296417Sdim    const uint32_t num_bases = compiler_type.GetNumDirectBaseClasses();
612254721Semaste
613254721Semaste    if (num_bases > 0)
614254721Semaste    {
615254721Semaste        for (uint32_t i = 0; i < num_bases; ++i)
616254721Semaste        {
617296417Sdim            CompilerType base_class_type = compiler_type.GetDirectBaseClassAtIndex(i, nullptr);
618254721Semaste
619254721Semaste            PrivateAutoCompleteMembers (frame,
620254721Semaste                                        partial_member_name,
621254721Semaste                                        partial_path,
622254721Semaste                                        prefix_path,
623254721Semaste                                        base_class_type.GetCanonicalType(),
624254721Semaste                                        matches,
625254721Semaste                                        word_complete);
626254721Semaste        }
627254721Semaste    }
628254721Semaste
629296417Sdim    const uint32_t num_vbases = compiler_type.GetNumVirtualBaseClasses();
630254721Semaste
631254721Semaste    if (num_vbases > 0)
632254721Semaste    {
633254721Semaste        for (uint32_t i = 0; i < num_vbases; ++i)
634254721Semaste        {
635296417Sdim            CompilerType vbase_class_type = compiler_type.GetVirtualBaseClassAtIndex(i,nullptr);
636254721Semaste
637254721Semaste            PrivateAutoCompleteMembers (frame,
638254721Semaste                                        partial_member_name,
639254721Semaste                                        partial_path,
640254721Semaste                                        prefix_path,
641254721Semaste                                        vbase_class_type.GetCanonicalType(),
642254721Semaste                                        matches,
643254721Semaste                                        word_complete);
644254721Semaste        }
645254721Semaste    }
646254721Semaste
647254721Semaste    // We are in a type parsing child members
648296417Sdim    const uint32_t num_fields = compiler_type.GetNumFields();
649254721Semaste
650254721Semaste    if (num_fields > 0)
651254721Semaste    {
652254721Semaste        for (uint32_t i = 0; i < num_fields; ++i)
653254721Semaste        {
654254721Semaste            std::string member_name;
655254721Semaste
656296417Sdim            CompilerType member_compiler_type = compiler_type.GetFieldAtIndex (i, member_name, nullptr, nullptr, nullptr);
657254721Semaste
658254721Semaste            if (partial_member_name.empty() ||
659254721Semaste                member_name.find(partial_member_name) == 0)
660254721Semaste            {
661254721Semaste                if (member_name == partial_member_name)
662254721Semaste                {
663254721Semaste                    PrivateAutoComplete (frame,
664254721Semaste                                         partial_path,
665254721Semaste                                         prefix_path + member_name, // Anything that has been resolved already will be in here
666296417Sdim                                         member_compiler_type.GetCanonicalType(),
667254721Semaste                                         matches,
668254721Semaste                                         word_complete);
669254721Semaste                }
670254721Semaste                else
671254721Semaste                {
672254721Semaste                    matches.AppendString (prefix_path + member_name);
673254721Semaste                }
674254721Semaste            }
675254721Semaste        }
676254721Semaste    }
677254721Semaste}
678254721Semaste
679254721Semastestatic void
680254721SemastePrivateAutoComplete (StackFrame *frame,
681254721Semaste                     const std::string &partial_path,
682254721Semaste                     const std::string &prefix_path, // Anything that has been resolved already will be in here
683296417Sdim                     const CompilerType& compiler_type,
684254721Semaste                     StringList &matches,
685254721Semaste                     bool &word_complete)
686254721Semaste{
687254721Semaste//    printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = '%s'\n", prefix_path.c_str(), partial_path.c_str());
688254721Semaste    std::string remaining_partial_path;
689254721Semaste
690296417Sdim    const lldb::TypeClass type_class = compiler_type.GetTypeClass();
691254721Semaste    if (partial_path.empty())
692254721Semaste    {
693296417Sdim        if (compiler_type.IsValid())
694254721Semaste        {
695254721Semaste            switch (type_class)
696254721Semaste            {
697254721Semaste                default:
698254721Semaste                case eTypeClassArray:
699254721Semaste                case eTypeClassBlockPointer:
700254721Semaste                case eTypeClassBuiltin:
701254721Semaste                case eTypeClassComplexFloat:
702254721Semaste                case eTypeClassComplexInteger:
703254721Semaste                case eTypeClassEnumeration:
704254721Semaste                case eTypeClassFunction:
705254721Semaste                case eTypeClassMemberPointer:
706254721Semaste                case eTypeClassReference:
707254721Semaste                case eTypeClassTypedef:
708254721Semaste                case eTypeClassVector:
709254721Semaste                    {
710254721Semaste                        matches.AppendString (prefix_path);
711254721Semaste                        word_complete = matches.GetSize() == 1;
712254721Semaste                    }
713254721Semaste                    break;
714254721Semaste
715254721Semaste                case eTypeClassClass:
716254721Semaste                case eTypeClassStruct:
717254721Semaste                case eTypeClassUnion:
718254721Semaste                    if (prefix_path.back() != '.')
719254721Semaste                        matches.AppendString (prefix_path + '.');
720254721Semaste                    break;
721254721Semaste
722254721Semaste                case eTypeClassObjCObject:
723254721Semaste                case eTypeClassObjCInterface:
724254721Semaste                    break;
725254721Semaste                case eTypeClassObjCObjectPointer:
726254721Semaste                case eTypeClassPointer:
727254721Semaste                    {
728254721Semaste                        bool omit_empty_base_classes = true;
729296417Sdim                        if (compiler_type.GetNumChildren (omit_empty_base_classes) > 0)
730254721Semaste                            matches.AppendString (prefix_path + "->");
731254721Semaste                        else
732254721Semaste                        {
733254721Semaste                            matches.AppendString (prefix_path);
734254721Semaste                            word_complete = true;
735254721Semaste                        }
736254721Semaste                    }
737254721Semaste                    break;
738254721Semaste            }
739254721Semaste        }
740254721Semaste        else
741254721Semaste        {
742254721Semaste            if (frame)
743254721Semaste            {
744254721Semaste                const bool get_file_globals = true;
745254721Semaste
746254721Semaste                VariableList *variable_list = frame->GetVariableList(get_file_globals);
747254721Semaste
748258054Semaste                if (variable_list)
749254721Semaste                {
750258054Semaste                    const size_t num_variables = variable_list->GetSize();
751258054Semaste                    for (size_t i=0; i<num_variables; ++i)
752258054Semaste                    {
753258054Semaste                        Variable *variable = variable_list->GetVariableAtIndex(i).get();
754258054Semaste                        matches.AppendString (variable->GetName().AsCString());
755258054Semaste                    }
756254721Semaste                }
757254721Semaste            }
758254721Semaste        }
759254721Semaste    }
760254721Semaste    else
761254721Semaste    {
762254721Semaste        const char ch = partial_path[0];
763254721Semaste        switch (ch)
764254721Semaste        {
765254721Semaste        case '*':
766254721Semaste            if (prefix_path.empty())
767254721Semaste            {
768254721Semaste                PrivateAutoComplete (frame,
769254721Semaste                                     partial_path.substr(1),
770254721Semaste                                     std::string("*"),
771296417Sdim                                     compiler_type,
772254721Semaste                                     matches,
773254721Semaste                                     word_complete);
774254721Semaste            }
775254721Semaste            break;
776254721Semaste
777254721Semaste        case '&':
778254721Semaste            if (prefix_path.empty())
779254721Semaste            {
780254721Semaste                PrivateAutoComplete (frame,
781254721Semaste                                     partial_path.substr(1),
782254721Semaste                                     std::string("&"),
783296417Sdim                                     compiler_type,
784254721Semaste                                     matches,
785254721Semaste                                     word_complete);
786254721Semaste            }
787254721Semaste            break;
788254721Semaste
789254721Semaste        case '-':
790254721Semaste            if (partial_path[1] == '>' && !prefix_path.empty())
791254721Semaste            {
792254721Semaste                switch (type_class)
793254721Semaste                {
794254721Semaste                    case lldb::eTypeClassPointer:
795254721Semaste                        {
796296417Sdim                            CompilerType pointee_type(compiler_type.GetPointeeType());
797254721Semaste                            if (partial_path[2])
798254721Semaste                            {
799254721Semaste                                // If there is more after the "->", then search deeper
800254721Semaste                                PrivateAutoComplete (frame,
801254721Semaste                                                     partial_path.substr(2),
802254721Semaste                                                     prefix_path + "->",
803254721Semaste                                                     pointee_type.GetCanonicalType(),
804254721Semaste                                                     matches,
805254721Semaste                                                     word_complete);
806254721Semaste                            }
807254721Semaste                            else
808254721Semaste                            {
809254721Semaste                                // Nothing after the "->", so list all members
810254721Semaste                                PrivateAutoCompleteMembers (frame,
811254721Semaste                                                            std::string(),
812254721Semaste                                                            std::string(),
813254721Semaste                                                            prefix_path + "->",
814254721Semaste                                                            pointee_type.GetCanonicalType(),
815254721Semaste                                                            matches,
816254721Semaste                                                            word_complete);
817254721Semaste                            }
818254721Semaste                        }
819254721Semaste                    default:
820254721Semaste                        break;
821254721Semaste                }
822254721Semaste            }
823254721Semaste            break;
824254721Semaste
825254721Semaste        case '.':
826296417Sdim            if (compiler_type.IsValid())
827254721Semaste            {
828254721Semaste                switch (type_class)
829254721Semaste                {
830254721Semaste                    case lldb::eTypeClassUnion:
831254721Semaste                    case lldb::eTypeClassStruct:
832254721Semaste                    case lldb::eTypeClassClass:
833254721Semaste                        if (partial_path[1])
834254721Semaste                        {
835254721Semaste                            // If there is more after the ".", then search deeper
836254721Semaste                            PrivateAutoComplete (frame,
837254721Semaste                                                 partial_path.substr(1),
838254721Semaste                                                 prefix_path + ".",
839296417Sdim                                                 compiler_type,
840254721Semaste                                                 matches,
841254721Semaste                                                 word_complete);
842254721Semaste
843254721Semaste                        }
844254721Semaste                        else
845254721Semaste                        {
846254721Semaste                            // Nothing after the ".", so list all members
847254721Semaste                            PrivateAutoCompleteMembers (frame,
848254721Semaste                                                        std::string(),
849254721Semaste                                                        partial_path,
850254721Semaste                                                        prefix_path + ".",
851296417Sdim                                                        compiler_type,
852254721Semaste                                                        matches,
853254721Semaste                                                        word_complete);
854254721Semaste                        }
855254721Semaste                    default:
856254721Semaste                        break;
857254721Semaste                }
858254721Semaste            }
859254721Semaste            break;
860254721Semaste        default:
861254721Semaste            if (isalpha(ch) || ch == '_' || ch == '$')
862254721Semaste            {
863254721Semaste                const size_t partial_path_len = partial_path.size();
864254721Semaste                size_t pos = 1;
865254721Semaste                while (pos < partial_path_len)
866254721Semaste                {
867254721Semaste                    const char curr_ch = partial_path[pos];
868254721Semaste                    if (isalnum(curr_ch) || curr_ch == '_'  || curr_ch == '$')
869254721Semaste                    {
870254721Semaste                        ++pos;
871254721Semaste                        continue;
872254721Semaste                    }
873254721Semaste                    break;
874254721Semaste                }
875254721Semaste
876254721Semaste                std::string token(partial_path, 0, pos);
877254721Semaste                remaining_partial_path = partial_path.substr(pos);
878254721Semaste
879296417Sdim                if (compiler_type.IsValid())
880254721Semaste                {
881254721Semaste                    PrivateAutoCompleteMembers (frame,
882254721Semaste                                                token,
883254721Semaste                                                remaining_partial_path,
884254721Semaste                                                prefix_path,
885296417Sdim                                                compiler_type,
886254721Semaste                                                matches,
887254721Semaste                                                word_complete);
888254721Semaste                }
889254721Semaste                else if (frame)
890254721Semaste                {
891254721Semaste                    // We haven't found our variable yet
892254721Semaste                    const bool get_file_globals = true;
893254721Semaste
894254721Semaste                    VariableList *variable_list = frame->GetVariableList(get_file_globals);
895254721Semaste
896262528Semaste                    if (!variable_list)
897262528Semaste                        break;
898262528Semaste
899254721Semaste                    const size_t num_variables = variable_list->GetSize();
900254721Semaste                    for (size_t i=0; i<num_variables; ++i)
901254721Semaste                    {
902254721Semaste                        Variable *variable = variable_list->GetVariableAtIndex(i).get();
903262528Semaste
904262528Semaste                        if (!variable)
905262528Semaste                            continue;
906262528Semaste
907254721Semaste                        const char *variable_name = variable->GetName().AsCString();
908254721Semaste                        if (strstr(variable_name, token.c_str()) == variable_name)
909254721Semaste                        {
910254721Semaste                            if (strcmp (variable_name, token.c_str()) == 0)
911254721Semaste                            {
912254721Semaste                                Type *variable_type = variable->GetType();
913254721Semaste                                if (variable_type)
914254721Semaste                                {
915296417Sdim                                    CompilerType variable_compiler_type (variable_type->GetForwardCompilerType ());
916254721Semaste                                    PrivateAutoComplete (frame,
917254721Semaste                                                         remaining_partial_path,
918254721Semaste                                                         prefix_path + token, // Anything that has been resolved already will be in here
919296417Sdim                                                         variable_compiler_type.GetCanonicalType(),
920254721Semaste                                                         matches,
921254721Semaste                                                         word_complete);
922254721Semaste                                }
923254721Semaste                                else
924254721Semaste                                {
925254721Semaste                                    matches.AppendString (prefix_path + variable_name);
926254721Semaste                                }
927254721Semaste                            }
928254721Semaste                            else if (remaining_partial_path.empty())
929254721Semaste                            {
930254721Semaste                                matches.AppendString (prefix_path + variable_name);
931254721Semaste                            }
932254721Semaste                        }
933254721Semaste                    }
934254721Semaste                }
935254721Semaste            }
936254721Semaste            break;
937254721Semaste        }
938254721Semaste    }
939254721Semaste}
940254721Semaste
941254721Semaste
942254721Semaste
943254721Semastesize_t
944254721SemasteVariable::AutoComplete (const ExecutionContext &exe_ctx,
945254721Semaste                        const char *partial_path_cstr,
946254721Semaste                        StringList &matches,
947254721Semaste                        bool &word_complete)
948254721Semaste{
949254721Semaste    word_complete = false;
950254721Semaste    std::string partial_path;
951254721Semaste    std::string prefix_path;
952296417Sdim    CompilerType compiler_type;
953254721Semaste    if (partial_path_cstr && partial_path_cstr[0])
954254721Semaste        partial_path = partial_path_cstr;
955254721Semaste
956254721Semaste    PrivateAutoComplete (exe_ctx.GetFramePtr(),
957254721Semaste                         partial_path,
958254721Semaste                         prefix_path,
959296417Sdim                         compiler_type,
960254721Semaste                         matches,
961254721Semaste                         word_complete);
962254721Semaste
963254721Semaste    return matches.GetSize();
964254721Semaste}
965254721Semaste
966