diff options
Diffstat (limited to 'lldb/source/Target/StackFrame.cpp')
-rw-r--r-- | lldb/source/Target/StackFrame.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 7281ba427e4..20946532188 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -478,6 +478,159 @@ StackFrame::GetVariableList (bool get_file_globals) return m_variable_list_sp.get(); } +ValueObjectSP +StackFrame::GetValueForVariableExpressionPath (const char *var_expr) +{ + bool deref = false; + bool address_of = false; + ValueObjectSP valobj_sp; + const bool get_file_globals = true; + VariableList *variable_list = GetVariableList (get_file_globals); + + if (variable_list) + { + // If first character is a '*', then show pointer contents + if (var_expr[0] == '*') + { + deref = true; + var_expr++; // Skip the '*' + } + else if (var_expr[0] == '&') + { + address_of = true; + var_expr++; // Skip the '&' + } + + std::string var_path (var_expr); + size_t separator_idx = var_path.find_first_of(".-["); + + ConstString name_const_string; + if (separator_idx == std::string::npos) + name_const_string.SetCString (var_path.c_str()); + else + name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx); + + VariableSP var_sp (variable_list->FindVariable(name_const_string)); + if (var_sp) + { + valobj_sp = GetValueObjectForFrameVariable (var_sp); + + var_path.erase (0, name_const_string.GetLength ()); + // We are dumping at least one child + while (separator_idx != std::string::npos) + { + // Calculate the next separator index ahead of time + ValueObjectSP child_valobj_sp; + const char separator_type = var_path[0]; + switch (separator_type) + { + + case '-': + if (var_path.size() >= 2 && var_path[1] != '>') + return ValueObjectSP(); + + var_path.erase (0, 1); // Remove the '-' + // Fall through + case '.': + { + // We either have a pointer type and need to verify + // valobj_sp is a pointer, or we have a member of a + // class/union/struct being accessed with the . syntax + // and need to verify we don't have a pointer. + const bool is_ptr = var_path[0] == '>'; + + if (valobj_sp->IsPointerType () != is_ptr) + { + // Incorrect use of "." with a pointer, or "->" with + // a class/union/struct instance or reference. + return ValueObjectSP(); + } + + var_path.erase (0, 1); // Remove the '.' or '>' + separator_idx = var_path.find_first_of(".-["); + ConstString child_name; + if (separator_idx == std::string::npos) + child_name.SetCString (var_path.c_str()); + else + child_name.SetCStringWithLength(var_path.c_str(), separator_idx); + + child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true); + if (!child_valobj_sp) + { + // No child member with name "child_name" + return ValueObjectSP(); + } + // Remove the child name from the path + var_path.erase(0, child_name.GetLength()); + } + break; + + case '[': + // Array member access, or treating pointer as an array + if (var_path.size() > 2) // Need at least two brackets and a number + { + char *end = NULL; + int32_t child_index = ::strtol (&var_path[1], &end, 0); + if (end && *end == ']') + { + + if (valobj_sp->IsPointerType ()) + { + child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true); + } + else + { + child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true); + } + + if (!child_valobj_sp) + { + // Invalid array index... + return ValueObjectSP(); + } + + // Erase the array member specification '[%i]' where + // %i is the array index + var_path.erase(0, (end - var_path.c_str()) + 1); + separator_idx = var_path.find_first_of(".-["); + + // Break out early from the switch since we were + // able to find the child member + break; + } + } + return ValueObjectSP(); + + default: + // Failure... + return ValueObjectSP(); + } + + if (child_valobj_sp) + valobj_sp = child_valobj_sp; + + if (var_path.empty()) + break; + + } + if (valobj_sp) + { + if (deref) + { + ValueObjectSP deref_valobj_sp (valobj_sp->Dereference(this, NULL)); + valobj_sp = deref_valobj_sp; + } + else if (address_of) + { + ValueObjectSP address_of_valobj_sp (valobj_sp->AddressOf()); + valobj_sp = address_of_valobj_sp; + } + } + return valobj_sp; + } + } + return ValueObjectSP(); +} bool StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr) |