blob: 5665e4702ca68d59dd4d0b4c2c15614b8adb9f5a [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Variable.cpp --------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Symbol/Variable.h"
11
Greg Clayton1f746072012-08-29 21:13:06 +000012#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000013#include "lldb/Core/Stream.h"
Greg Clayton83c5cd92010-11-14 22:13:40 +000014#include "lldb/Core/RegularExpression.h"
Greg Clayton884fb692011-07-08 21:46:14 +000015#include "lldb/Core/ValueObject.h"
16#include "lldb/Core/ValueObjectVariable.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "lldb/Symbol/Block.h"
18#include "lldb/Symbol/Function.h"
19#include "lldb/Symbol/SymbolContext.h"
20#include "lldb/Symbol/Type.h"
Greg Clayton884fb692011-07-08 21:46:14 +000021#include "lldb/Symbol/VariableList.h"
Greg Claytonafacd142011-09-02 01:15:17 +000022#include "lldb/Target/ABI.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000023#include "lldb/Target/Process.h"
Greg Clayton9da7bd02010-08-24 21:05:24 +000024#include "lldb/Target/RegisterContext.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000025#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026#include "lldb/Target/Thread.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000027#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028
29using namespace lldb;
30using namespace lldb_private;
31
32//----------------------------------------------------------------------
33// Variable constructor
34//----------------------------------------------------------------------
Greg Clayton83c5cd92010-11-14 22:13:40 +000035Variable::Variable
36(
37 lldb::user_id_t uid,
38 const char *name,
Siva Chandra0783ab92015-03-24 18:32:27 +000039 const char *mangled, // The mangled or fully qualified name of the variable.
Greg Claytond1767f02011-12-08 02:13:16 +000040 const lldb::SymbolFileTypeSP &symfile_type_sp,
Greg Clayton83c5cd92010-11-14 22:13:40 +000041 ValueType scope,
42 SymbolContextScope *context,
43 Declaration* decl_ptr,
44 const DWARFExpression& location,
45 bool external,
46 bool artificial
47) :
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048 UserID(uid),
49 m_name(name),
Siva Chandra0783ab92015-03-24 18:32:27 +000050 m_mangled (ConstString(mangled)),
Greg Claytond1767f02011-12-08 02:13:16 +000051 m_symfile_type_sp(symfile_type_sp),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052 m_scope(scope),
Greg Clayton59e8fc1c2010-08-30 18:11:35 +000053 m_owner_scope(context),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000054 m_declaration(decl_ptr),
55 m_location(location),
56 m_external(external),
57 m_artificial(artificial)
58{
59}
60
61//----------------------------------------------------------------------
62// Destructor
63//----------------------------------------------------------------------
64Variable::~Variable()
65{
66}
67
68
Greg Clayton83c5cd92010-11-14 22:13:40 +000069const ConstString&
70Variable::GetName() const
71{
Siva Chandra0783ab92015-03-24 18:32:27 +000072 const ConstString &name = m_mangled.GetName();
73 if (name)
74 return name;
Greg Clayton83c5cd92010-11-14 22:13:40 +000075 return m_name;
76}
77
78bool
79Variable::NameMatches (const RegularExpression& regex) const
80{
81 if (regex.Execute (m_name.AsCString()))
82 return true;
83 return m_mangled.NameMatches (regex);
84}
85
Greg Claytond1767f02011-12-08 02:13:16 +000086Type *
87Variable::GetType()
88{
89 if (m_symfile_type_sp)
90 return m_symfile_type_sp->GetType();
Ed Masted4612ad2014-04-20 13:17:36 +000091 return nullptr;
Greg Claytond1767f02011-12-08 02:13:16 +000092}
93
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094void
95Variable::Dump(Stream *s, bool show_context) const
96{
Saleem Abdulrasool324a1032014-04-04 04:06:10 +000097 s->Printf("%p: ", static_cast<const void*>(this));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098 s->Indent();
99 *s << "Variable" << (const UserID&)*this;
100
101 if (m_name)
102 *s << ", name = \"" << m_name << "\"";
103
Greg Claytond1767f02011-12-08 02:13:16 +0000104 if (m_symfile_type_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000105 {
Greg Claytond1767f02011-12-08 02:13:16 +0000106 Type *type = m_symfile_type_sp->GetType();
107 if (type)
108 {
109 *s << ", type = {" << type->GetID() << "} " << (void*)type << " (";
110 type->DumpTypeName(s);
111 s->PutChar(')');
112 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113 }
114
115 if (m_scope != eValueTypeInvalid)
116 {
117 s->PutCString(", scope = ");
118 switch (m_scope)
119 {
120 case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break;
121 case eValueTypeVariableArgument: s->PutCString("parameter"); break;
122 case eValueTypeVariableLocal: s->PutCString("local"); break;
123 default: *s << "??? (" << m_scope << ')';
124 }
125 }
126
Ed Masted4612ad2014-04-20 13:17:36 +0000127 if (show_context && m_owner_scope != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128 {
129 s->PutCString(", context = ( ");
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000130 m_owner_scope->DumpSymbolContext(s);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000131 s->PutCString(" )");
132 }
133
Greg Clayton6dbd3982010-09-15 05:51:24 +0000134 bool show_fullpaths = false;
135 m_declaration.Dump(s, show_fullpaths);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136
137 if (m_location.IsValid())
138 {
139 s->PutCString(", location = ");
Greg Clayton016a95e2010-09-14 02:20:48 +0000140 lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
141 if (m_location.IsLocationList())
142 {
143 SymbolContext variable_sc;
144 m_owner_scope->CalculateSymbolContext(&variable_sc);
145 if (variable_sc.function)
146 loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
147 }
Ed Masted4612ad2014-04-20 13:17:36 +0000148 ABI *abi = nullptr;
Greg Claytonafacd142011-09-02 01:15:17 +0000149 if (m_owner_scope)
150 {
Greg Claytone72dfb32012-02-24 01:59:29 +0000151 ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule());
152 if (module_sp)
153 abi = ABI::FindPlugin (module_sp->GetArchitecture()).get();
Greg Claytonafacd142011-09-02 01:15:17 +0000154 }
155 m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr, abi);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156 }
157
158 if (m_external)
159 s->PutCString(", external");
160
161 if (m_artificial)
162 s->PutCString(", artificial");
163
164 s->EOL();
165}
166
Greg Clayton45ba8542011-07-10 19:21:23 +0000167bool
168Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module)
169{
170 bool dumped_declaration_info = false;
171 if (m_owner_scope)
172 {
173 SymbolContext sc;
174 m_owner_scope->CalculateSymbolContext(&sc);
Ed Masted4612ad2014-04-20 13:17:36 +0000175 sc.block = nullptr;
Greg Clayton45ba8542011-07-10 19:21:23 +0000176 sc.line_entry.Clear();
177 bool show_inlined_frames = false;
Jason Molendaaff1b352014-10-10 23:07:36 +0000178 const bool show_function_arguments = true;
Jason Molendac980fa92015-02-13 23:24:21 +0000179 const bool show_function_name = true;
Greg Clayton45ba8542011-07-10 19:21:23 +0000180
181 dumped_declaration_info = sc.DumpStopContext (s,
Ed Masted4612ad2014-04-20 13:17:36 +0000182 nullptr,
Greg Clayton45ba8542011-07-10 19:21:23 +0000183 Address(),
184 show_fullpaths,
185 show_module,
Jason Molendaaff1b352014-10-10 23:07:36 +0000186 show_inlined_frames,
Jason Molendac980fa92015-02-13 23:24:21 +0000187 show_function_arguments,
188 show_function_name);
Greg Clayton45ba8542011-07-10 19:21:23 +0000189
190 if (sc.function)
191 s->PutChar(':');
192 }
193 if (m_declaration.DumpStopContext (s, false))
194 dumped_declaration_info = true;
195 return dumped_declaration_info;
196}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197
198size_t
199Variable::MemorySize() const
200{
201 return sizeof(Variable);
202}
203
204
205void
206Variable::CalculateSymbolContext (SymbolContext *sc)
207{
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000208 if (m_owner_scope)
Greg Clayton2501e5e2015-01-15 02:59:20 +0000209 {
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000210 m_owner_scope->CalculateSymbolContext(sc);
Greg Clayton2501e5e2015-01-15 02:59:20 +0000211 sc->variable = this;
212 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000213 else
Greg Clayton72310352013-02-23 04:12:47 +0000214 sc->Clear(false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000215}
216
Greg Clayton007d5be2011-05-30 00:49:24 +0000217bool
Jason Molendab57e4a12013-11-04 09:33:30 +0000218Variable::LocationIsValidForFrame (StackFrame *frame)
Greg Clayton007d5be2011-05-30 00:49:24 +0000219{
220 // Is the variable is described by a single location?
221 if (!m_location.IsLocationList())
222 {
223 // Yes it is, the location is valid.
224 return true;
225 }
226
227 if (frame)
228 {
Greg Clayton007d5be2011-05-30 00:49:24 +0000229 Function *function = frame->GetSymbolContext(eSymbolContextFunction).function;
230 if (function)
231 {
Greg Claytond9e416c2012-02-18 05:35:26 +0000232 TargetSP target_sp (frame->CalculateTarget());
233
234 addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target_sp.get());
Greg Clayton007d5be2011-05-30 00:49:24 +0000235 if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
236 return false;
237 // It is a location list. We just need to tell if the location
238 // list contains the current address when converted to a load
239 // address
240 return m_location.LocationListContainsAddress (loclist_base_load_addr,
Greg Claytond9e416c2012-02-18 05:35:26 +0000241 frame->GetFrameCodeAddress().GetLoadAddress (target_sp.get()));
Greg Clayton007d5be2011-05-30 00:49:24 +0000242 }
243 }
244 return false;
245}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246
247bool
Greg Claytonc749eb82011-07-11 05:12:02 +0000248Variable::LocationIsValidForAddress (const Address &address)
249{
250 // Be sure to resolve the address to section offset prior to
251 // calling this function.
252 if (address.IsSectionOffset())
253 {
254 SymbolContext sc;
255 CalculateSymbolContext(&sc);
Greg Claytone72dfb32012-02-24 01:59:29 +0000256 if (sc.module_sp == address.GetModule())
Greg Claytonc749eb82011-07-11 05:12:02 +0000257 {
258 // Is the variable is described by a single location?
259 if (!m_location.IsLocationList())
260 {
261 // Yes it is, the location is valid.
262 return true;
263 }
264
265 if (sc.function)
266 {
267 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
268 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
269 return false;
270 // It is a location list. We just need to tell if the location
271 // list contains the current address when converted to a load
272 // address
273 return m_location.LocationListContainsAddress (loclist_base_file_addr,
274 address.GetFileAddress());
275 }
276 }
277 }
278 return false;
279}
280
281bool
Jason Molendab57e4a12013-11-04 09:33:30 +0000282Variable::IsInScope (StackFrame *frame)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000283{
284 switch (m_scope)
285 {
Greg Clayton007d5be2011-05-30 00:49:24 +0000286 case eValueTypeRegister:
287 case eValueTypeRegisterSet:
Ed Masted4612ad2014-04-20 13:17:36 +0000288 return frame != nullptr;
Greg Clayton007d5be2011-05-30 00:49:24 +0000289
290 case eValueTypeConstResult:
Greg Clayton007d5be2011-05-30 00:49:24 +0000291 case eValueTypeVariableGlobal:
292 case eValueTypeVariableStatic:
Greg Claytondaf515f2011-07-09 20:12:33 +0000293 return true;
294
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000295 case eValueTypeVariableArgument:
296 case eValueTypeVariableLocal:
Greg Clayton007d5be2011-05-30 00:49:24 +0000297 if (frame)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000298 {
299 // We don't have a location list, we just need to see if the block
300 // that this variable was defined in is currently
Greg Clayton6f00abd2010-09-14 03:16:58 +0000301 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
302 if (deepest_frame_block)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000303 {
304 SymbolContext variable_sc;
305 CalculateSymbolContext (&variable_sc);
Greg Clayton007d5be2011-05-30 00:49:24 +0000306 // Check for static or global variable defined at the compile unit
307 // level that wasn't defined in a block
Ed Masted4612ad2014-04-20 13:17:36 +0000308 if (variable_sc.block == nullptr)
Greg Clayton007d5be2011-05-30 00:49:24 +0000309 return true;
310
Greg Clayton6f00abd2010-09-14 03:16:58 +0000311 if (variable_sc.block == deepest_frame_block)
Greg Clayton016a95e2010-09-14 02:20:48 +0000312 return true;
Greg Clayton6f00abd2010-09-14 03:16:58 +0000313 return variable_sc.block->Contains (deepest_frame_block);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000314 }
315 }
316 break;
317
318 default:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000319 break;
320 }
321 return false;
322}
323
Greg Clayton884fb692011-07-08 21:46:14 +0000324Error
325Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
326 ExecutionContextScope *scope,
327 GetVariableCallback callback,
328 void *baton,
329 VariableList &variable_list,
330 ValueObjectList &valobj_list)
331{
332 Error error;
333 if (variable_expr_path && callback)
334 {
335 switch (variable_expr_path[0])
336 {
337 case '*':
338 {
339 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
340 scope,
341 callback,
342 baton,
343 variable_list,
344 valobj_list);
345 if (error.Success())
346 {
347 for (uint32_t i=0; i<valobj_list.GetSize(); )
348 {
349 Error tmp_error;
350 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error));
351 if (tmp_error.Fail())
352 {
353 variable_list.RemoveVariableAtIndex (i);
354 valobj_list.RemoveValueObjectAtIndex (i);
355 }
356 else
357 {
358 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
359 ++i;
360 }
361 }
362 }
363 else
364 {
365 error.SetErrorString ("unknown error");
366 }
367 return error;
368 }
369 break;
370
371 case '&':
372 {
373 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
374 scope,
375 callback,
376 baton,
377 variable_list,
378 valobj_list);
379 if (error.Success())
380 {
381 for (uint32_t i=0; i<valobj_list.GetSize(); )
382 {
383 Error tmp_error;
384 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
385 if (tmp_error.Fail())
386 {
387 variable_list.RemoveVariableAtIndex (i);
388 valobj_list.RemoveValueObjectAtIndex (i);
389 }
390 else
391 {
392 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
393 ++i;
394 }
395 }
396 }
397 else
398 {
399 error.SetErrorString ("unknown error");
400 }
401 return error;
402 }
403 break;
404
405 default:
406 {
Greg Claytonbc43cab2013-04-03 21:37:16 +0000407 static RegularExpression g_regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)");
408 RegularExpression::Match regex_match(1);
409 if (g_regex.Execute(variable_expr_path, &regex_match))
Greg Clayton884fb692011-07-08 21:46:14 +0000410 {
411 std::string variable_name;
Greg Claytonbc43cab2013-04-03 21:37:16 +0000412 if (regex_match.GetMatchAtIndex(variable_expr_path, 1, variable_name))
Greg Clayton884fb692011-07-08 21:46:14 +0000413 {
414 variable_list.Clear();
415 if (callback (baton, variable_name.c_str(), variable_list))
416 {
417 uint32_t i=0;
418 while (i < variable_list.GetSize())
419 {
420 VariableSP var_sp (variable_list.GetVariableAtIndex (i));
421 ValueObjectSP valobj_sp;
422 if (var_sp)
423 {
424 ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
425 if (variable_valobj_sp)
426 {
Greg Clayton958d4eb2013-05-20 16:50:51 +0000427 const char *variable_sub_expr_path = variable_expr_path + variable_name.size();
428 if (*variable_sub_expr_path)
Greg Clayton884fb692011-07-08 21:46:14 +0000429 {
Ed Masted4612ad2014-04-20 13:17:36 +0000430 const char* first_unparsed = nullptr;
Greg Clayton884fb692011-07-08 21:46:14 +0000431 ValueObject::ExpressionPathScanEndReason reason_to_stop;
432 ValueObject::ExpressionPathEndResultType final_value_type;
433 ValueObject::GetValueForExpressionPathOptions options;
434 ValueObject::ExpressionPathAftermath final_task_on_target;
435
Greg Clayton958d4eb2013-05-20 16:50:51 +0000436 valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_sub_expr_path,
Greg Clayton884fb692011-07-08 21:46:14 +0000437 &first_unparsed,
438 &reason_to_stop,
439 &final_value_type,
440 options,
441 &final_task_on_target);
442 if (!valobj_sp)
443 {
444 error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
Greg Clayton958d4eb2013-05-20 16:50:51 +0000445 variable_sub_expr_path,
Greg Clayton884fb692011-07-08 21:46:14 +0000446 var_sp->GetName().GetCString());
447 }
448 }
449 else
450 {
451 // Just the name of a variable with no extras
452 valobj_sp = variable_valobj_sp;
453 }
454 }
455 }
456
457 if (!var_sp || !valobj_sp)
458 {
459 variable_list.RemoveVariableAtIndex (i);
460 }
461 else
462 {
463 valobj_list.Append(valobj_sp);
464 ++i;
465 }
466 }
467
468 if (variable_list.GetSize() > 0)
469 {
470 error.Clear();
471 return error;
472 }
473 }
474 }
475 }
Greg Clayton885b4b72013-05-20 16:52:10 +0000476 error.SetErrorStringWithFormat ("unable to extract a variable name from '%s'", variable_expr_path);
Greg Clayton884fb692011-07-08 21:46:14 +0000477 }
478 break;
479 }
480 }
481 error.SetErrorString ("unknown error");
482 return error;
483}
484
Greg Claytonc749eb82011-07-11 05:12:02 +0000485bool
486Variable::DumpLocationForAddress (Stream *s, const Address &address)
487{
488 // Be sure to resolve the address to section offset prior to
489 // calling this function.
490 if (address.IsSectionOffset())
491 {
492 SymbolContext sc;
493 CalculateSymbolContext(&sc);
Greg Claytone72dfb32012-02-24 01:59:29 +0000494 if (sc.module_sp == address.GetModule())
Greg Claytonc749eb82011-07-11 05:12:02 +0000495 {
Ed Masted4612ad2014-04-20 13:17:36 +0000496 ABI *abi = nullptr;
Greg Claytonafacd142011-09-02 01:15:17 +0000497 if (m_owner_scope)
498 {
Greg Claytone72dfb32012-02-24 01:59:29 +0000499 ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule());
500 if (module_sp)
501 abi = ABI::FindPlugin (module_sp->GetArchitecture()).get();
Greg Claytonafacd142011-09-02 01:15:17 +0000502 }
503
Greg Claytonc749eb82011-07-11 05:12:02 +0000504 const addr_t file_addr = address.GetFileAddress();
505 if (sc.function)
506 {
507 if (sc.function->GetAddressRange().ContainsFileAddress(address))
508 {
509 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
510 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
511 return false;
512 return m_location.DumpLocationForAddress (s,
513 eDescriptionLevelBrief,
514 loclist_base_file_addr,
Greg Claytonafacd142011-09-02 01:15:17 +0000515 file_addr,
516 abi);
Greg Claytonc749eb82011-07-11 05:12:02 +0000517 }
518 }
519 return m_location.DumpLocationForAddress (s,
520 eDescriptionLevelBrief,
521 LLDB_INVALID_ADDRESS,
Greg Claytonafacd142011-09-02 01:15:17 +0000522 file_addr,
523 abi);
Greg Claytonc749eb82011-07-11 05:12:02 +0000524 }
525 }
526 return false;
Greg Claytonf21fead2013-05-14 23:43:18 +0000527}
Greg Claytonc749eb82011-07-11 05:12:02 +0000528
Greg Claytonf21fead2013-05-14 23:43:18 +0000529
530static void
Jason Molendab57e4a12013-11-04 09:33:30 +0000531PrivateAutoComplete (StackFrame *frame,
Greg Claytonf21fead2013-05-14 23:43:18 +0000532 const std::string &partial_path,
533 const std::string &prefix_path, // Anything that has been resolved already will be in here
534 const ClangASTType& clang_type,
535 StringList &matches,
536 bool &word_complete);
537
538static void
Jason Molendab57e4a12013-11-04 09:33:30 +0000539PrivateAutoCompleteMembers (StackFrame *frame,
Greg Claytonf21fead2013-05-14 23:43:18 +0000540 const std::string &partial_member_name,
541 const std::string &partial_path,
542 const std::string &prefix_path, // Anything that has been resolved already will be in here
543 const ClangASTType& clang_type,
544 StringList &matches,
545 bool &word_complete);
546
547static void
Jason Molendab57e4a12013-11-04 09:33:30 +0000548PrivateAutoCompleteMembers (StackFrame *frame,
Greg Claytonf21fead2013-05-14 23:43:18 +0000549 const std::string &partial_member_name,
550 const std::string &partial_path,
551 const std::string &prefix_path, // Anything that has been resolved already will be in here
552 const ClangASTType& clang_type,
553 StringList &matches,
554 bool &word_complete)
555{
556
557 // We are in a type parsing child members
Pavel Labathc7c30eb2015-06-08 23:38:06 +0000558 const uint32_t num_bases = clang_type.GetNumDirectBaseClasses();
Greg Claytonf21fead2013-05-14 23:43:18 +0000559
560 if (num_bases > 0)
561 {
562 for (uint32_t i = 0; i < num_bases; ++i)
563 {
Pavel Labathc7c30eb2015-06-08 23:38:06 +0000564 ClangASTType base_class_type (clang_type.GetDirectBaseClassAtIndex (i, nullptr));
Greg Claytonf21fead2013-05-14 23:43:18 +0000565
566 PrivateAutoCompleteMembers (frame,
567 partial_member_name,
568 partial_path,
569 prefix_path,
570 base_class_type.GetCanonicalType(),
571 matches,
572 word_complete);
573 }
574 }
575
Pavel Labathc7c30eb2015-06-08 23:38:06 +0000576 const uint32_t num_vbases = clang_type.GetNumVirtualBaseClasses();
Greg Claytonf21fead2013-05-14 23:43:18 +0000577
578 if (num_vbases > 0)
579 {
580 for (uint32_t i = 0; i < num_vbases; ++i)
581 {
Pavel Labathc7c30eb2015-06-08 23:38:06 +0000582 ClangASTType vbase_class_type (clang_type.GetVirtualBaseClassAtIndex(i,nullptr));
Greg Claytonf21fead2013-05-14 23:43:18 +0000583
584 PrivateAutoCompleteMembers (frame,
585 partial_member_name,
586 partial_path,
587 prefix_path,
588 vbase_class_type.GetCanonicalType(),
589 matches,
590 word_complete);
591 }
592 }
593
594 // We are in a type parsing child members
Greg Clayton57ee3062013-07-11 22:46:58 +0000595 const uint32_t num_fields = clang_type.GetNumFields();
Greg Claytonf21fead2013-05-14 23:43:18 +0000596
597 if (num_fields > 0)
598 {
599 for (uint32_t i = 0; i < num_fields; ++i)
600 {
601 std::string member_name;
602
Ed Masted4612ad2014-04-20 13:17:36 +0000603 ClangASTType member_clang_type = clang_type.GetFieldAtIndex (i, member_name, nullptr, nullptr, nullptr);
Greg Claytonf21fead2013-05-14 23:43:18 +0000604
605 if (partial_member_name.empty() ||
606 member_name.find(partial_member_name) == 0)
607 {
608 if (member_name == partial_member_name)
609 {
Greg Claytonf21fead2013-05-14 23:43:18 +0000610 PrivateAutoComplete (frame,
611 partial_path,
612 prefix_path + member_name, // Anything that has been resolved already will be in here
613 member_clang_type.GetCanonicalType(),
614 matches,
615 word_complete);
616 }
617 else
618 {
619 matches.AppendString (prefix_path + member_name);
620 }
621 }
622 }
623 }
624}
625
626static void
Jason Molendab57e4a12013-11-04 09:33:30 +0000627PrivateAutoComplete (StackFrame *frame,
Greg Claytonf21fead2013-05-14 23:43:18 +0000628 const std::string &partial_path,
629 const std::string &prefix_path, // Anything that has been resolved already will be in here
630 const ClangASTType& clang_type,
631 StringList &matches,
632 bool &word_complete)
633{
634// printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = '%s'\n", prefix_path.c_str(), partial_path.c_str());
635 std::string remaining_partial_path;
636
637 const lldb::TypeClass type_class = clang_type.GetTypeClass();
638 if (partial_path.empty())
639 {
640 if (clang_type.IsValid())
641 {
642 switch (type_class)
643 {
644 default:
645 case eTypeClassArray:
646 case eTypeClassBlockPointer:
647 case eTypeClassBuiltin:
648 case eTypeClassComplexFloat:
649 case eTypeClassComplexInteger:
650 case eTypeClassEnumeration:
651 case eTypeClassFunction:
652 case eTypeClassMemberPointer:
653 case eTypeClassReference:
654 case eTypeClassTypedef:
655 case eTypeClassVector:
656 {
657 matches.AppendString (prefix_path);
658 word_complete = matches.GetSize() == 1;
659 }
660 break;
661
662 case eTypeClassClass:
663 case eTypeClassStruct:
664 case eTypeClassUnion:
665 if (prefix_path.back() != '.')
666 matches.AppendString (prefix_path + '.');
667 break;
668
669 case eTypeClassObjCObject:
670 case eTypeClassObjCInterface:
671 break;
672 case eTypeClassObjCObjectPointer:
673 case eTypeClassPointer:
674 {
675 bool omit_empty_base_classes = true;
Greg Clayton57ee3062013-07-11 22:46:58 +0000676 if (clang_type.GetNumChildren (omit_empty_base_classes) > 0)
Greg Claytonf21fead2013-05-14 23:43:18 +0000677 matches.AppendString (prefix_path + "->");
678 else
679 {
680 matches.AppendString (prefix_path);
681 word_complete = true;
682 }
683 }
684 break;
685 }
686 }
687 else
688 {
689 if (frame)
690 {
691 const bool get_file_globals = true;
692
693 VariableList *variable_list = frame->GetVariableList(get_file_globals);
694
Jason Molendaa3a542f2013-10-09 02:39:26 +0000695 if (variable_list)
Greg Claytonf21fead2013-05-14 23:43:18 +0000696 {
Jason Molendaa3a542f2013-10-09 02:39:26 +0000697 const size_t num_variables = variable_list->GetSize();
698 for (size_t i=0; i<num_variables; ++i)
699 {
700 Variable *variable = variable_list->GetVariableAtIndex(i).get();
701 matches.AppendString (variable->GetName().AsCString());
702 }
Greg Claytonf21fead2013-05-14 23:43:18 +0000703 }
704 }
705 }
706 }
707 else
708 {
709 const char ch = partial_path[0];
710 switch (ch)
711 {
712 case '*':
713 if (prefix_path.empty())
714 {
715 PrivateAutoComplete (frame,
716 partial_path.substr(1),
717 std::string("*"),
718 clang_type,
719 matches,
720 word_complete);
721 }
722 break;
723
724 case '&':
725 if (prefix_path.empty())
726 {
727 PrivateAutoComplete (frame,
728 partial_path.substr(1),
729 std::string("&"),
730 clang_type,
731 matches,
732 word_complete);
733 }
734 break;
735
736 case '-':
737 if (partial_path[1] == '>' && !prefix_path.empty())
738 {
739 switch (type_class)
740 {
741 case lldb::eTypeClassPointer:
742 {
Greg Clayton57ee3062013-07-11 22:46:58 +0000743 ClangASTType pointee_type(clang_type.GetPointeeType());
Greg Claytonf21fead2013-05-14 23:43:18 +0000744 if (partial_path[2])
745 {
746 // If there is more after the "->", then search deeper
747 PrivateAutoComplete (frame,
748 partial_path.substr(2),
749 prefix_path + "->",
750 pointee_type.GetCanonicalType(),
751 matches,
752 word_complete);
753 }
754 else
755 {
756 // Nothing after the "->", so list all members
757 PrivateAutoCompleteMembers (frame,
758 std::string(),
759 std::string(),
760 prefix_path + "->",
761 pointee_type.GetCanonicalType(),
762 matches,
763 word_complete);
764 }
765 }
766 default:
767 break;
768 }
769 }
770 break;
771
772 case '.':
773 if (clang_type.IsValid())
774 {
775 switch (type_class)
776 {
777 case lldb::eTypeClassUnion:
778 case lldb::eTypeClassStruct:
779 case lldb::eTypeClassClass:
780 if (partial_path[1])
781 {
782 // If there is more after the ".", then search deeper
783 PrivateAutoComplete (frame,
784 partial_path.substr(1),
785 prefix_path + ".",
786 clang_type,
787 matches,
788 word_complete);
789
790 }
791 else
792 {
793 // Nothing after the ".", so list all members
794 PrivateAutoCompleteMembers (frame,
795 std::string(),
796 partial_path,
797 prefix_path + ".",
798 clang_type,
799 matches,
800 word_complete);
801 }
802 default:
803 break;
804 }
805 }
806 break;
807 default:
808 if (isalpha(ch) || ch == '_' || ch == '$')
809 {
810 const size_t partial_path_len = partial_path.size();
811 size_t pos = 1;
812 while (pos < partial_path_len)
813 {
814 const char curr_ch = partial_path[pos];
815 if (isalnum(curr_ch) || curr_ch == '_' || curr_ch == '$')
816 {
817 ++pos;
818 continue;
819 }
820 break;
821 }
822
823 std::string token(partial_path, 0, pos);
824 remaining_partial_path = partial_path.substr(pos);
825
826 if (clang_type.IsValid())
827 {
828 PrivateAutoCompleteMembers (frame,
829 token,
830 remaining_partial_path,
831 prefix_path,
832 clang_type,
833 matches,
834 word_complete);
835 }
836 else if (frame)
837 {
838 // We haven't found our variable yet
839 const bool get_file_globals = true;
840
841 VariableList *variable_list = frame->GetVariableList(get_file_globals);
842
Enrico Granata16f35ea2013-12-21 08:44:28 +0000843 if (!variable_list)
844 break;
845
Greg Claytonf21fead2013-05-14 23:43:18 +0000846 const size_t num_variables = variable_list->GetSize();
847 for (size_t i=0; i<num_variables; ++i)
848 {
849 Variable *variable = variable_list->GetVariableAtIndex(i).get();
Enrico Granata16f35ea2013-12-21 08:44:28 +0000850
851 if (!variable)
852 continue;
853
Greg Claytonf21fead2013-05-14 23:43:18 +0000854 const char *variable_name = variable->GetName().AsCString();
855 if (strstr(variable_name, token.c_str()) == variable_name)
856 {
857 if (strcmp (variable_name, token.c_str()) == 0)
858 {
859 Type *variable_type = variable->GetType();
860 if (variable_type)
861 {
Greg Clayton57ee3062013-07-11 22:46:58 +0000862 ClangASTType variable_clang_type (variable_type->GetClangForwardType());
Greg Claytonf21fead2013-05-14 23:43:18 +0000863 PrivateAutoComplete (frame,
864 remaining_partial_path,
865 prefix_path + token, // Anything that has been resolved already will be in here
866 variable_clang_type.GetCanonicalType(),
867 matches,
868 word_complete);
869 }
870 else
871 {
872 matches.AppendString (prefix_path + variable_name);
873 }
874 }
875 else if (remaining_partial_path.empty())
876 {
877 matches.AppendString (prefix_path + variable_name);
878 }
879 }
880 }
881 }
882 }
883 break;
884 }
885 }
886}
887
888
889
890size_t
891Variable::AutoComplete (const ExecutionContext &exe_ctx,
892 const char *partial_path_cstr,
893 StringList &matches,
894 bool &word_complete)
895{
896 word_complete = false;
897 std::string partial_path;
898 std::string prefix_path;
899 ClangASTType clang_type;
900 if (partial_path_cstr && partial_path_cstr[0])
901 partial_path = partial_path_cstr;
902
903 PrivateAutoComplete (exe_ctx.GetFramePtr(),
904 partial_path,
905 prefix_path,
906 clang_type,
907 matches,
908 word_complete);
909
910 return matches.GetSize();
Greg Claytonc749eb82011-07-11 05:12:02 +0000911}
912