<rdar://problem/11870357>
Allow "frame variable" to find ivars without the need for "this->" or "self->". llvm-svn: 160211
This commit is contained in:
parent
c22e8d1192
commit
685c88c5a8
|
@ -262,6 +262,22 @@ public:
|
|||
return m_children.front().get();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the variable list for this block only.
|
||||
///
|
||||
/// @param[in] can_create
|
||||
/// If \b true, the variables can be parsed if they already
|
||||
/// haven't been, else the current state of the block will be
|
||||
/// returned.
|
||||
///
|
||||
/// @return
|
||||
/// A variable list shared pointer that contains all variables
|
||||
/// for this block.
|
||||
//------------------------------------------------------------------
|
||||
lldb::VariableListSP
|
||||
GetBlockVariableList (bool can_create);
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the variable list for this block and optionally all child
|
||||
/// blocks if \a get_child_variables is \b true.
|
||||
|
@ -278,7 +294,7 @@ public:
|
|||
/// point.
|
||||
///
|
||||
/// @param[in] add_inline_child_block_variables
|
||||
/// If this is \b false, no child variables of child blocks
|
||||
/// If this is \b false, no child variables of child blocks
|
||||
/// that are inlined functions will be gotten. If \b true then
|
||||
/// all child variables will be added regardless of whether they
|
||||
/// come from inlined functions or not.
|
||||
|
@ -287,10 +303,6 @@ public:
|
|||
/// A variable list shared pointer that contains all variables
|
||||
/// for this block.
|
||||
//------------------------------------------------------------------
|
||||
lldb::VariableListSP
|
||||
GetBlockVariableList (bool can_create);
|
||||
|
||||
|
||||
uint32_t
|
||||
AppendBlockVariables (bool can_create,
|
||||
bool get_child_block_variables,
|
||||
|
@ -345,7 +357,7 @@ public:
|
|||
}
|
||||
|
||||
clang::DeclContext *
|
||||
GetClangDeclContextForInlinedFunction();
|
||||
GetClangDeclContext();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the memory cost of this object.
|
||||
|
|
|
@ -237,6 +237,12 @@ public:
|
|||
return GetTranslationUnitDecl (getASTContext());
|
||||
}
|
||||
|
||||
static bool
|
||||
GetClassMethodInfoForDeclContext (clang::DeclContext *decl_ctx,
|
||||
lldb::LanguageType &language,
|
||||
bool &is_instance_method,
|
||||
ConstString &language_object_name);
|
||||
|
||||
static lldb::clang_type_t
|
||||
CopyType(clang::ASTContext *dest_context,
|
||||
clang::ASTContext *source_context,
|
||||
|
|
|
@ -220,6 +220,56 @@ public:
|
|||
uint32_t
|
||||
GetResolvedMask () const;
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Find a block that defines the function represented by this
|
||||
/// symbol context.
|
||||
///
|
||||
/// If this symbol context points to a block that is an inlined
|
||||
/// function, or is contained within an inlined function, the block
|
||||
/// that defines the inlined function is returned.
|
||||
///
|
||||
/// If this symbol context has no block in it, or the block is not
|
||||
/// itself an inlined function block or contained within one, we
|
||||
/// return the top level function block.
|
||||
///
|
||||
/// This is a handy function to call when you want to get the block
|
||||
/// whose variable list will include the arguments for the function
|
||||
/// that is represented by this symbol context (whether the function
|
||||
/// is an inline function or not).
|
||||
///
|
||||
/// @return
|
||||
/// The block object pointer that defines the function that is
|
||||
/// represented by this symbol context object, NULL otherwise.
|
||||
//------------------------------------------------------------------
|
||||
Block *
|
||||
GetFunctionBlock ();
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// If this symbol context represents a function that is a method,
|
||||
/// return true and provide information about the method.
|
||||
///
|
||||
/// @param[out] language
|
||||
/// If \b true is returned, the language for the method.
|
||||
///
|
||||
/// @param[out] is_instance_method
|
||||
/// If \b true is returned, \b true if this is a instance method,
|
||||
/// \b false if this is a static/class function.
|
||||
///
|
||||
/// @param[out] language_object_name
|
||||
/// If \b true is returned, the name of the artificial variable
|
||||
/// for the language ("this" for C++, "self" for ObjC).
|
||||
///
|
||||
/// @return
|
||||
/// \b True if this symbol context represents a function that
|
||||
/// is a method of a class, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
GetFunctionMethodInfo (lldb::LanguageType &language,
|
||||
bool &is_instance_method,
|
||||
ConstString &language_object_name);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Find a name of the innermost function for the symbol context.
|
||||
///
|
||||
|
|
|
@ -50,6 +50,11 @@ public:
|
|||
lldb::VariableSP
|
||||
FindVariable (const ConstString& name);
|
||||
|
||||
// Find the argument variable that represents the language specific
|
||||
// object pointer ("this" in C++, or "self" in Objective C).
|
||||
lldb::VariableSP
|
||||
FindArtificialObjectVariable (lldb::LanguageType language) const;
|
||||
|
||||
uint32_t
|
||||
FindVariableIndex (const lldb::VariableSP &var_sp);
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ public:
|
|||
eExpressionPathOptionCheckPtrVsMember = (1u << 0),
|
||||
eExpressionPathOptionsNoFragileObjcIvar = (1u << 1),
|
||||
eExpressionPathOptionsNoSyntheticChildren = (1u << 2),
|
||||
eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3)
|
||||
eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3),
|
||||
eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4)
|
||||
};
|
||||
//------------------------------------------------------------------
|
||||
// Constructors and Destructors
|
||||
|
|
|
@ -534,7 +534,7 @@ SBFrame::GetValueForVariablePath (const char *var_path, DynamicValueType use_dyn
|
|||
Error error;
|
||||
ValueObjectSP value_sp (frame->GetValueForVariableExpressionPath (var_path,
|
||||
use_dynamic,
|
||||
StackFrame::eExpressionPathOptionCheckPtrVsMember,
|
||||
StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
|
||||
var_sp,
|
||||
error));
|
||||
sb_value.SetSP(value_sp);
|
||||
|
|
|
@ -483,7 +483,8 @@ protected:
|
|||
else // No regex, either exact variable names or variable expressions.
|
||||
{
|
||||
Error error;
|
||||
uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
|
||||
uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
|
||||
StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
|
||||
lldb::VariableSP var_sp;
|
||||
valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr,
|
||||
m_varobj_options.use_dynamic,
|
||||
|
|
|
@ -1015,7 +1015,8 @@ protected:
|
|||
|
||||
// Things have checked out ok...
|
||||
Error error;
|
||||
uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
|
||||
uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
|
||||
StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
|
||||
valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0),
|
||||
eNoDynamicValues,
|
||||
expr_path_options,
|
||||
|
|
|
@ -987,48 +987,6 @@ ScanBracketedRange (const char* var_name_begin,
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
static ValueObjectSP
|
||||
ExpandExpressionPath (ValueObject* valobj,
|
||||
StackFrame* frame,
|
||||
bool* do_deref_pointer,
|
||||
const char* var_name_begin,
|
||||
const char* var_name_final,
|
||||
Error& error)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
StreamString sstring;
|
||||
VariableSP var_sp;
|
||||
|
||||
if (*do_deref_pointer)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("been told to deref_pointer by caller");
|
||||
sstring.PutChar('*');
|
||||
}
|
||||
else if (valobj->IsDereferenceOfParent() && ClangASTContext::IsPointerType(valobj->GetParent()->GetClangType()) && !valobj->IsArrayItemForPointer())
|
||||
{
|
||||
if (log)
|
||||
log->Printf("decided to deref_pointer myself");
|
||||
sstring.PutChar('*');
|
||||
*do_deref_pointer = true;
|
||||
}
|
||||
|
||||
valobj->GetExpressionPath(sstring, true, ValueObject::eGetExpressionPathFormatHonorPointers);
|
||||
if (log)
|
||||
log->Printf("expression path to expand in phase 0: %s",sstring.GetData());
|
||||
sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3);
|
||||
if (log)
|
||||
log->Printf("expression path to expand in phase 1: %s",sstring.GetData());
|
||||
std::string name = std::string(sstring.GetData());
|
||||
ValueObjectSP target = frame->GetValueForVariableExpressionPath (name.c_str(),
|
||||
eNoDynamicValues,
|
||||
0,
|
||||
var_sp,
|
||||
error);
|
||||
return target;
|
||||
}
|
||||
|
||||
static ValueObjectSP
|
||||
ExpandIndexedExpression (ValueObject* valobj,
|
||||
uint32_t index,
|
||||
|
|
|
@ -2443,12 +2443,13 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
|
|||
if (!sym_ctx.function)
|
||||
return;
|
||||
|
||||
clang::DeclContext *decl_context;
|
||||
|
||||
if (sym_ctx.block && sym_ctx.block->GetInlinedFunctionInfo())
|
||||
decl_context = sym_ctx.block->GetClangDeclContextForInlinedFunction();
|
||||
else
|
||||
decl_context = sym_ctx.function->GetClangDeclContext();
|
||||
// Get the block that defines the function
|
||||
Block *function_block = sym_ctx.GetFunctionBlock();
|
||||
|
||||
if (!function_block)
|
||||
return;
|
||||
|
||||
clang::DeclContext *decl_context = function_block->GetClangDeclContext();
|
||||
|
||||
if (!decl_context)
|
||||
return;
|
||||
|
@ -2501,12 +2502,13 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
|
|||
if (!sym_ctx.function)
|
||||
return;
|
||||
|
||||
clang::DeclContext *decl_context;
|
||||
// Get the block that defines the function
|
||||
Block *function_block = sym_ctx.GetFunctionBlock();
|
||||
|
||||
if (sym_ctx.block && sym_ctx.block->GetInlinedFunctionInfo())
|
||||
decl_context = sym_ctx.block->GetClangDeclContextForInlinedFunction();
|
||||
else
|
||||
decl_context = sym_ctx.function->GetClangDeclContext();
|
||||
if (!function_block)
|
||||
return;
|
||||
|
||||
clang::DeclContext *decl_context = function_block->GetClangDeclContext();
|
||||
|
||||
if (!decl_context)
|
||||
return;
|
||||
|
|
|
@ -115,13 +115,14 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
|
|||
if (!sym_ctx.function)
|
||||
return;
|
||||
|
||||
clang::DeclContext *decl_context;
|
||||
// Find the block that defines the function represented by "sym_ctx"
|
||||
Block *function_block = sym_ctx.GetFunctionBlock();
|
||||
|
||||
if (sym_ctx.block && sym_ctx.block->GetInlinedFunctionInfo())
|
||||
decl_context = sym_ctx.block->GetClangDeclContextForInlinedFunction();
|
||||
else
|
||||
decl_context = sym_ctx.function->GetClangDeclContext();
|
||||
|
||||
if (!function_block)
|
||||
return;
|
||||
|
||||
clang::DeclContext *decl_context = function_block->GetClangDeclContext();
|
||||
|
||||
if (!decl_context)
|
||||
return;
|
||||
|
||||
|
@ -131,24 +132,22 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
|
|||
{
|
||||
if (m_enforce_valid_object)
|
||||
{
|
||||
VariableList *vars = frame->GetVariableList(false);
|
||||
lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
|
||||
|
||||
const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
|
||||
|
||||
if (!vars)
|
||||
if (!variable_list_sp)
|
||||
{
|
||||
err.SetErrorToGenericError();
|
||||
err.SetErrorString(thisErrorString);
|
||||
return;
|
||||
}
|
||||
|
||||
lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
|
||||
lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
|
||||
|
||||
if (!this_var ||
|
||||
!this_var->IsInScope(frame) ||
|
||||
!this_var->LocationIsValidForFrame (frame))
|
||||
if (!this_var_sp ||
|
||||
!this_var_sp->IsInScope(frame) ||
|
||||
!this_var_sp->LocationIsValidForFrame (frame))
|
||||
{
|
||||
err.SetErrorToGenericError();
|
||||
err.SetErrorString(thisErrorString);
|
||||
return;
|
||||
}
|
||||
|
@ -164,24 +163,22 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
|
|||
{
|
||||
if (m_enforce_valid_object)
|
||||
{
|
||||
VariableList *vars = frame->GetVariableList(false);
|
||||
lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
|
||||
|
||||
const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
|
||||
|
||||
if (!vars)
|
||||
if (!variable_list_sp)
|
||||
{
|
||||
err.SetErrorToGenericError();
|
||||
err.SetErrorString(selfErrorString);
|
||||
return;
|
||||
}
|
||||
|
||||
lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
|
||||
lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
|
||||
|
||||
if (!self_var ||
|
||||
!self_var->IsInScope(frame) ||
|
||||
!self_var->LocationIsValidForFrame (frame))
|
||||
if (!self_variable_sp ||
|
||||
!self_variable_sp->IsInScope(frame) ||
|
||||
!self_variable_sp->LocationIsValidForFrame (frame))
|
||||
{
|
||||
err.SetErrorToGenericError();
|
||||
err.SetErrorString(selfErrorString);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -542,7 +542,7 @@ Block::AppendVariables
|
|||
}
|
||||
|
||||
clang::DeclContext *
|
||||
Block::GetClangDeclContextForInlinedFunction()
|
||||
Block::GetClangDeclContext()
|
||||
{
|
||||
SymbolContext sc;
|
||||
|
||||
|
|
|
@ -6330,3 +6330,49 @@ ClangASTContext::GetAsDeclContext (clang::ObjCMethodDecl *objc_method_decl)
|
|||
return llvm::dyn_cast<clang::DeclContext>(objc_method_decl);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ClangASTContext::GetClassMethodInfoForDeclContext (clang::DeclContext *decl_ctx,
|
||||
lldb::LanguageType &language,
|
||||
bool &is_instance_method,
|
||||
ConstString &language_object_name)
|
||||
{
|
||||
language_object_name.Clear();
|
||||
language = eLanguageTypeUnknown;
|
||||
is_instance_method = false;
|
||||
|
||||
if (decl_ctx)
|
||||
{
|
||||
if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_ctx))
|
||||
{
|
||||
if (method_decl->isStatic())
|
||||
{
|
||||
is_instance_method = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
language_object_name.SetCString("this");
|
||||
is_instance_method = true;
|
||||
}
|
||||
language = eLanguageTypeC_plus_plus;
|
||||
return true;
|
||||
}
|
||||
else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_ctx))
|
||||
{
|
||||
// Both static and instance methods have a "self" object in objective C
|
||||
language_object_name.SetCString("self");
|
||||
if (method_decl->isInstanceMethod())
|
||||
{
|
||||
is_instance_method = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_instance_method = false;
|
||||
}
|
||||
language = eLanguageTypeObjC;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/Interpreter/Args.h"
|
||||
#include "lldb/Symbol/Block.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
#include "lldb/Symbol/CompileUnit.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Symbol/Symbol.h"
|
||||
|
@ -535,7 +537,61 @@ SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc,
|
|||
return false;
|
||||
}
|
||||
|
||||
ConstString
|
||||
Block *
|
||||
SymbolContext::GetFunctionBlock ()
|
||||
{
|
||||
if (function)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
// If this symbol context has a block, check to see if this block
|
||||
// is itself, or is contained within a block with inlined function
|
||||
// information. If so, then the inlined block is the block that
|
||||
// defines the function.
|
||||
Block *inlined_block = block->GetContainingInlinedBlock();
|
||||
if (inlined_block)
|
||||
return inlined_block;
|
||||
|
||||
// The block in this symbol context is not inside an inlined
|
||||
// block, so the block that defines the function is the function's
|
||||
// top level block, which is returned below.
|
||||
}
|
||||
|
||||
// There is no block information in this symbol context, so we must
|
||||
// assume that the block that is desired is the top level block of
|
||||
// the function itself.
|
||||
return &function->GetBlock(true);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
SymbolContext::GetFunctionMethodInfo (lldb::LanguageType &language,
|
||||
bool &is_instance_method,
|
||||
ConstString &language_object_name)
|
||||
|
||||
|
||||
{
|
||||
Block *function_block = GetFunctionBlock ();
|
||||
if (function_block)
|
||||
{
|
||||
clang::DeclContext *decl_context = function_block->GetClangDeclContext();
|
||||
|
||||
if (decl_context)
|
||||
{
|
||||
return ClangASTContext::GetClassMethodInfoForDeclContext (decl_context,
|
||||
language,
|
||||
is_instance_method,
|
||||
language_object_name);
|
||||
}
|
||||
}
|
||||
language = eLanguageTypeUnknown;
|
||||
is_instance_method = false;
|
||||
language_object_name.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
ConstString
|
||||
SymbolContext::GetFunctionName (Mangled::NamePreference preference)
|
||||
{
|
||||
if (function)
|
||||
|
|
|
@ -176,3 +176,40 @@ VariableList::Dump(Stream *s, bool show_context) const
|
|||
}
|
||||
}
|
||||
|
||||
lldb::VariableSP
|
||||
VariableList::FindArtificialObjectVariable (lldb::LanguageType language) const
|
||||
{
|
||||
lldb::VariableSP object_variable_sp;
|
||||
ConstString object_variable_name;
|
||||
switch (language)
|
||||
{
|
||||
case eLanguageTypeC_plus_plus:
|
||||
object_variable_name.SetCString("this");
|
||||
break;
|
||||
|
||||
case eLanguageTypeObjC:
|
||||
case eLanguageTypeObjC_plus_plus:
|
||||
object_variable_name.SetCString("self");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (object_variable_name)
|
||||
{
|
||||
const_iterator pos, end = m_variables.end();
|
||||
for (pos = m_variables.begin(); pos != end; ++pos)
|
||||
{
|
||||
Variable *variable = pos->get();
|
||||
if (variable->IsArtificial() &&
|
||||
variable->GetScope() == eValueTypeVariableArgument &&
|
||||
variable->GetName() == object_variable_name)
|
||||
{
|
||||
object_variable_sp = *pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return object_variable_sp;
|
||||
}
|
||||
|
||||
|
|
|
@ -513,7 +513,7 @@ StackFrame::GetInScopeVariableList (bool get_file_globals)
|
|||
|
||||
|
||||
ValueObjectSP
|
||||
StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
|
||||
StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
|
||||
DynamicValueType use_dynamic,
|
||||
uint32_t options,
|
||||
VariableSP &var_sp,
|
||||
|
@ -562,13 +562,42 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
|
|||
name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
|
||||
|
||||
var_sp = variable_list->FindVariable(name_const_string);
|
||||
|
||||
bool synthetically_added_instance_object = false;
|
||||
|
||||
if (var_sp)
|
||||
{
|
||||
var_path.erase (0, name_const_string.GetLength ());
|
||||
}
|
||||
else if (options & eExpressionPathOptionsAllowDirectIVarAccess)
|
||||
{
|
||||
// Check for direct ivars access which helps us with implicit
|
||||
// access to ivars with the "this->" or "self->"
|
||||
GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock);
|
||||
lldb::LanguageType method_language = eLanguageTypeUnknown;
|
||||
bool is_instance_method = false;
|
||||
ConstString method_object_name;
|
||||
if (m_sc.GetFunctionMethodInfo (method_language, is_instance_method, method_object_name))
|
||||
{
|
||||
if (is_instance_method && method_object_name)
|
||||
{
|
||||
var_sp = variable_list->FindVariable(method_object_name);
|
||||
if (var_sp)
|
||||
{
|
||||
separator_idx = 0;
|
||||
var_path.insert(0, "->");
|
||||
synthetically_added_instance_object = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (var_sp)
|
||||
{
|
||||
valobj_sp = GetValueObjectForFrameVariable (var_sp, use_dynamic);
|
||||
if (!valobj_sp)
|
||||
return valobj_sp;
|
||||
|
||||
var_path.erase (0, name_const_string.GetLength ());
|
||||
// We are dumping at least one child
|
||||
while (separator_idx != std::string::npos)
|
||||
{
|
||||
|
@ -651,23 +680,35 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
|
|||
if (no_synth_child || !child_valobj_sp)
|
||||
{
|
||||
// No child member with name "child_name"
|
||||
valobj_sp->GetExpressionPath (var_expr_path_strm, false);
|
||||
if (child_name)
|
||||
if (synthetically_added_instance_object)
|
||||
{
|
||||
error.SetErrorStringWithFormat ("\"%s\" is not a member of \"(%s) %s\"",
|
||||
child_name.GetCString(),
|
||||
valobj_sp->GetTypeName().AsCString("<invalid type>"),
|
||||
var_expr_path_strm.GetString().c_str());
|
||||
// We added a "this->" or "self->" to the beginning of the expression
|
||||
// and this is the first pointer ivar access, so just return the normal
|
||||
// error
|
||||
error.SetErrorStringWithFormat("no variable or instance variable named '%s' found in this frame",
|
||||
name_const_string.GetCString());
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorStringWithFormat ("incomplete expression path after \"%s\" in \"%s\"",
|
||||
var_expr_path_strm.GetString().c_str(),
|
||||
var_expr_cstr);
|
||||
valobj_sp->GetExpressionPath (var_expr_path_strm, false);
|
||||
if (child_name)
|
||||
{
|
||||
error.SetErrorStringWithFormat ("\"%s\" is not a member of \"(%s) %s\"",
|
||||
child_name.GetCString(),
|
||||
valobj_sp->GetTypeName().AsCString("<invalid type>"),
|
||||
var_expr_path_strm.GetString().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorStringWithFormat ("incomplete expression path after \"%s\" in \"%s\"",
|
||||
var_expr_path_strm.GetString().c_str(),
|
||||
var_expr_cstr);
|
||||
}
|
||||
}
|
||||
return ValueObjectSP();
|
||||
}
|
||||
}
|
||||
synthetically_added_instance_object = false;
|
||||
// Remove the child name from the path
|
||||
var_path.erase(0, child_name.GetLength());
|
||||
if (use_dynamic != eNoDynamicValues)
|
||||
|
|
Loading…
Reference in New Issue