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, ®ex_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