Fixed the "expression" command object to use the StackFrame::GetValueForExpressionPath()
function and also hooked up better error reporting for when things fail.
Fixed issues with trying to display children of pointers when none are
supposed to be shown (no children for function pointers, and more like this).
This was causing child value objects to be made that were correctly firing
an assertion.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@121841 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index cae7247..039c0ec 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -50,7 +50,8 @@
//----------------------------------------------------------------------
// SBTarget constructor
//----------------------------------------------------------------------
-SBTarget::SBTarget ()
+SBTarget::SBTarget () :
+ m_opaque_sp ()
{
}
diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp
index 1fecc88..2960362 100644
--- a/source/Commands/CommandObjectFrame.cpp
+++ b/source/Commands/CommandObjectFrame.cpp
@@ -586,175 +586,36 @@
}
else
{
- bool address_of = false;
- // If first character is a '*', then show pointer contents
- if (name_cstr[0] == '*')
+ Error error;
+ const bool check_ptr_vs_member = true;
+ valobj_sp = exe_ctx.frame->GetValueForVariableExpressionPath (name_cstr, check_ptr_vs_member, error);
+ if (valobj_sp)
{
- ++ptr_depth;
- name_cstr++; // Skip the '*'
- }
- else if (name_cstr[0] == '&')
- {
- address_of = true;
- name_cstr++; // Skip the '&'
- }
-
- std::string var_path (name_cstr);
- 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);
-
- var_sp = variable_list->FindVariable(name_const_string);
- if (var_sp)
- {
- valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
-
- var_path.erase (0, name_const_string.GetLength ());
- // We are dumping at least one child
- while (separator_idx != std::string::npos)
+ if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
{
- // 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] != '>')
- {
- result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
- var_path.c_str());
- var_path.clear();
- valobj_sp.reset();
- break;
- }
- var_path.erase (0, 1); // Remove the '-'
- // Fall through
- case '.':
- {
- 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)
- {
- result.GetErrorStream().Printf ("error: can't find child of '%s' named '%s'\n",
- valobj_sp->GetName().AsCString(),
- child_name.GetCString());
- var_path.clear();
- valobj_sp.reset();
- break;
- }
- // 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)
- {
- result.GetErrorStream().Printf ("error: invalid array index %u in '%s'\n",
- child_index,
- valobj_sp->GetName().AsCString());
- var_path.clear();
- valobj_sp.reset();
- break;
- }
-
- // 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;
- }
- }
- result.GetErrorStream().Printf ("error: invalid array member specification for '%s' starting at '%s'\n",
- valobj_sp->GetName().AsCString(),
- var_path.c_str());
- var_path.clear();
- valobj_sp.reset();
- break;
-
- break;
-
- default:
- result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
- var_path.c_str());
- var_path.clear();
- valobj_sp.reset();
- separator_idx = std::string::npos;
- break;
- }
-
- if (child_valobj_sp)
- valobj_sp = child_valobj_sp;
-
- if (var_path.empty())
- break;
-
+ var_sp->GetDeclaration ().DumpStopContext (&s, false);
+ s.PutCString (": ");
}
-
- if (valobj_sp)
- {
- if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
- {
- var_sp->GetDeclaration ().DumpStopContext (&s, false);
- s.PutCString (": ");
- }
-
-
- if (address_of)
- {
- s.Printf("&%s = %s\n", name_cstr, valobj_sp->GetLocationAsCString (exe_ctx.frame));
- }
- else
- {
- ValueObject::DumpValueObject (result.GetOutputStream(),
- exe_ctx.frame,
- valobj_sp.get(),
- valobj_sp->GetParent() ? name_cstr : NULL,
- ptr_depth,
- 0,
- m_options.max_depth,
- m_options.show_types,
- m_options.show_location,
- m_options.use_objc,
- false,
- m_options.flat_output);
- }
- }
+ ValueObject::DumpValueObject (result.GetOutputStream(),
+ exe_ctx.frame,
+ valobj_sp.get(),
+ valobj_sp->GetParent() ? name_cstr : NULL,
+ ptr_depth,
+ 0,
+ m_options.max_depth,
+ m_options.show_types,
+ m_options.show_location,
+ m_options.use_objc,
+ false,
+ m_options.flat_output);
}
else
{
- result.GetErrorStream().Printf ("error: unable to find any variables named '%s'\n", name_cstr);
- var_path.clear();
+ const char *error_cstr = error.AsCString(NULL);
+ if (error_cstr)
+ result.GetErrorStream().Printf("error: %s\n", error_cstr);
+ else
+ result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr);
}
}
}
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index 60b1009..2f82d49 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -1203,10 +1203,11 @@
}
lldb::ValueObjectSP
-ValueObject::Dereference (ExecutionContextScope *exe_scope, Error *error_ptr)
+ValueObject::Dereference (ExecutionContextScope *exe_scope, Error &error)
{
lldb::ValueObjectSP valobj_sp;
- if (IsPointerType())
+ const bool is_pointer_type = IsPointerType();
+ if (is_pointer_type)
{
bool omit_empty_base_classes = true;
@@ -1249,98 +1250,46 @@
child_is_base_class));
}
}
+
+ if (valobj_sp)
+ {
+ error.Clear();
+ }
else
{
- if (error_ptr)
- error_ptr->SetErrorString("can't dereference a non-pointer value");
+ StreamString strm;
+ GetExpressionPath(strm);
+
+ if (is_pointer_type)
+ error.SetErrorStringWithFormat("dereference failed: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
+ else
+ error.SetErrorStringWithFormat("not a pointer type: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
}
return valobj_sp;
}
-
-
-//lldb::ValueObjectSP
-//ValueObject::Dereference (ExecutionContextScope *exe_scope, Error *error_ptr)
-//{
-// lldb::ValueObjectSP valobj_sp;
-// if (IsPointerType())
-// {
-// UpdateValueIfNeeded(exe_scope);
-// if (m_error.Success())
-// {
-// lldb::AddressType address_type = eAddressTypeInvalid;
-// const bool scalar_is_load_address = true;
-// lldb::addr_t addr = GetPointerValue (address_type, scalar_is_load_address);
-// if (addr != LLDB_INVALID_ADDRESS)
-// {
-// switch (address_type)
-// {
-// case eAddressTypeInvalid:
-// if (error_ptr)
-// error_ptr->SetErrorString("value is not in memory");
-// break;
-// case eAddressTypeFile:
-// case eAddressTypeLoad:
-// case eAddressTypeHost:
-// {
-// clang::ASTContext *ast = GetClangAST();
-// clang_type_t clang_type = ClangASTType::GetPointeeType (GetClangType());
-// if (ast && clang_type)
-// {
-// std::string name (1, '*');
-// name.append (m_name.AsCString(""));
-// valobj_sp.reset (new ValueObjectConstResult (ast,
-// ClangASTContext::CreatePointerType (ast, clang_type),
-// ConstString (name.c_str()),
-// addr,
-// address_type,
-// m_data.GetAddressByteSize()));
-// }
-// else
-// {
-// if (error_ptr)
-// error_ptr->SetErrorString("invalid clang type info");
-// }
-// }
-// break;
-// }
-// }
-// else
-// {
-// if (error_ptr)
-// error_ptr->SetErrorString("failed to extract pointer value");
-// }
-// }
-// else
-// {
-// if (error_ptr)
-// *error_ptr = m_error;
-// }
-// }
-// else
-// {
-// if (error_ptr)
-// error_ptr->SetErrorString("can't dereference a non-pointer value");
-// }
-//
-// return valobj_sp;
-//}
-
-lldb::ValueObjectSP
-ValueObject::AddressOf ()
+ lldb::ValueObjectSP
+ValueObject::AddressOf (Error &error)
{
lldb::ValueObjectSP valobj_sp;
-
lldb::AddressType address_type = eAddressTypeInvalid;
const bool scalar_is_load_address = false;
lldb::addr_t addr = GetAddressOf (address_type, scalar_is_load_address);
+ error.Clear();
if (addr != LLDB_INVALID_ADDRESS)
{
switch (address_type)
{
+ default:
case eAddressTypeInvalid:
+ {
+ StreamString expr_path_strm;
+ GetExpressionPath(expr_path_strm);
+ error.SetErrorStringWithFormat("'%s' is not in memory", expr_path_strm.GetString().c_str());
+ }
break;
+
case eAddressTypeFile:
case eAddressTypeLoad:
case eAddressTypeHost:
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index cd725ca..05643e63 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/source/Symbol/ClangASTContext.cpp
@@ -1901,7 +1901,10 @@
break;
}
break;
-
+
+ case clang::Type::Complex:
+ return 2;
+
case clang::Type::Record:
if (ClangASTType::IsDefined (clang_qual_type))
{
@@ -1995,12 +1998,15 @@
case clang::Type::Pointer:
{
PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
- QualType pointee_type = pointer_type->getPointeeType();
+ QualType pointee_type (pointer_type->getPointeeType());
uint32_t num_pointee_children = ClangASTContext::GetNumChildren (pointee_type.getAsOpaquePtr(),
omit_empty_base_classes);
- // If this type points to a simple type, then it has 1 child
if (num_pointee_children == 0)
- num_children = 1;
+ {
+ // We have a pointer to a pointee type that claims it has no children.
+ // We will want to look at
+ num_children = ClangASTContext::GetNumPointeeChildren (pointee_type.getAsOpaquePtr());
+ }
else
num_children = num_pointee_children;
}
@@ -2032,6 +2038,60 @@
return num_children;
}
+// If a pointer to a pointee type (the clang_type arg) says that it has no
+// children, then we either need to trust it, or override it and return a
+// different result. For example, an "int *" has one child that is an integer,
+// but a function pointer doesn't have any children. Likewise if a Record type
+// claims it has no children, then there really is nothing to show.
+uint32_t
+ClangASTContext::GetNumPointeeChildren (clang_type_t clang_type)
+{
+ if (clang_type == NULL)
+ return 0;
+
+ QualType qual_type(QualType::getFromOpaquePtr(clang_type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Builtin: return 1;
+ case clang::Type::Complex: return 2;
+ case clang::Type::Pointer: return 1;
+ case clang::Type::BlockPointer: return 0; // If block pointers don't have debug info, then no children for them
+ case clang::Type::LValueReference: return 1;
+ case clang::Type::RValueReference: return 1;
+ case clang::Type::MemberPointer: return 0;
+ case clang::Type::ConstantArray: return 0;
+ case clang::Type::IncompleteArray: return 0;
+ case clang::Type::VariableArray: return 0;
+ case clang::Type::DependentSizedArray: return 0;
+ case clang::Type::DependentSizedExtVector: return 0;
+ case clang::Type::Vector: return 0;
+ case clang::Type::ExtVector: return 0;
+ case clang::Type::FunctionProto: return 0; // When we function pointers, they have no children...
+ case clang::Type::FunctionNoProto: return 0; // When we function pointers, they have no children...
+ case clang::Type::UnresolvedUsing: return 0;
+ case clang::Type::Paren: return 0;
+ case clang::Type::Typedef: return ClangASTContext::GetNumPointeeChildren (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr());
+ case clang::Type::TypeOfExpr: return 0;
+ case clang::Type::TypeOf: return 0;
+ case clang::Type::Decltype: return 0;
+ case clang::Type::Record: return 0;
+ case clang::Type::Enum: return 1;
+ case clang::Type::Elaborated: return 1;
+ case clang::Type::TemplateTypeParm: return 1;
+ case clang::Type::SubstTemplateTypeParm: return 1;
+ case clang::Type::TemplateSpecialization: return 1;
+ case clang::Type::InjectedClassName: return 0;
+ case clang::Type::DependentName: return 1;
+ case clang::Type::DependentTemplateSpecialization: return 1;
+ case clang::Type::ObjCObject: return 0;
+ case clang::Type::ObjCInterface: return 0;
+ case clang::Type::ObjCObjectPointer: return 1;
+ default:
+ break;
+ }
+ return 0;
+}
clang_type_t
ClangASTContext::GetChildClangTypeAtIndex
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
index 2094653..341954f 100644
--- a/source/Target/StackFrame.cpp
+++ b/source/Target/StackFrame.cpp
@@ -18,6 +18,7 @@
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
@@ -479,156 +480,235 @@
}
ValueObjectSP
-StackFrame::GetValueForVariableExpressionPath (const char *var_expr)
+StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, bool check_ptr_vs_member, Error &error)
{
- 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 (var_expr_cstr && var_expr_cstr[0])
{
- // If first character is a '*', then show pointer contents
- if (var_expr[0] == '*')
+ error.Clear();
+ 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)
{
- 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)
+ // If first character is a '*', then show pointer contents
+ const char *var_expr = var_expr_cstr;
+ if (var_expr[0] == '*')
{
- // Calculate the next separator index ahead of time
- ValueObjectSP child_valobj_sp;
- const char separator_type = var_path[0];
- switch (separator_type)
+ 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(".-[=+~|&^%#@!/?,<>{}");
+ StreamString var_expr_path_strm;
+
+ 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)
{
-
- case '-':
- if (var_path.size() >= 2 && var_path[1] != '>')
- return ValueObjectSP();
-
- var_path.erase (0, 1); // Remove the '-'
- // Fall through
- case '.':
+ // Calculate the next separator index ahead of time
+ ValueObjectSP child_valobj_sp;
+ const char separator_type = var_path[0];
+ switch (separator_type)
{
- // 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.
+
+ case '-':
+ if (var_path.size() >= 2 && var_path[1] != '>')
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)
+ var_path.erase (0, 1); // Remove the '-'
+ // Fall through
+ case '.':
{
- // No child member with name "child_name"
- return ValueObjectSP();
- }
- // Remove the child name from the path
- var_path.erase(0, child_name.GetLength());
- }
- break;
+ const bool expr_is_ptr = var_path[0] == '>';
- 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);
- }
+ 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);
+
+ if (check_ptr_vs_member)
{
- child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
+ // 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 actual_is_ptr = valobj_sp->IsPointerType ();
+
+ if (actual_is_ptr != expr_is_ptr)
+ {
+ // Incorrect use of "." with a pointer, or "->" with
+ // a class/union/struct instance or reference.
+ valobj_sp->GetExpressionPath (var_expr_path_strm);
+ if (actual_is_ptr)
+ error.SetErrorStringWithFormat ("\"%s\" is a pointer and . was used to attempt to access \"%s\". Did you mean \"%s->%s\"?",
+ var_expr_path_strm.GetString().c_str(),
+ child_name.GetCString(),
+ var_expr_path_strm.GetString().c_str(),
+ var_path.c_str());
+ else
+ error.SetErrorStringWithFormat ("\"%s\" is not a pointer and -> was used to attempt to access \"%s\". Did you mean \"%s.%s\"?",
+ var_expr_path_strm.GetString().c_str(),
+ child_name.GetCString(),
+ var_expr_path_strm.GetString().c_str(),
+ var_path.c_str());
+ return ValueObjectSP();
+ }
}
+ child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
if (!child_valobj_sp)
{
- // Invalid array index...
+ // No child member with name "child_name"
+ valobj_sp->GetExpressionPath (var_expr_path_strm);
+ 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();
}
+ // Remove the child name from the path
+ var_path.erase(0, child_name.GetLength());
+ }
+ break;
- // 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(".-[");
+ 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 == ']')
+ {
- // Break out early from the switch since we were
- // able to find the child member
- break;
+ if (valobj_sp->IsPointerType ())
+ {
+ child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm);
+ error.SetErrorStringWithFormat ("failed to use pointer as array for index %i for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+ else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL))
+ {
+ child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm);
+ error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+ else
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm);
+ error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+
+ 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...
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm);
+ error.SetErrorStringWithFormat ("unexpected char '%c' encountered after \"%s\" in \"%s\"",
+ separator_type,
+ var_expr_path_strm.GetString().c_str(),
+ var_path.c_str());
+
+ return ValueObjectSP();
}
}
- return ValueObjectSP();
- default:
- // Failure...
- return ValueObjectSP();
+ if (child_valobj_sp)
+ valobj_sp = child_valobj_sp;
+
+ if (var_path.empty())
+ break;
+
}
-
- 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, error));
+ valobj_sp = deref_valobj_sp;
+ }
+ else if (address_of)
+ {
+ ValueObjectSP address_of_valobj_sp (valobj_sp->AddressOf(error));
+ valobj_sp = address_of_valobj_sp;
+ }
+ }
+ return valobj_sp;
}
- if (valobj_sp)
+ else
{
- 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;
- }
+ error.SetErrorStringWithFormat("no variable named '%s' found in this frame", name_const_string.GetCString());
}
- return valobj_sp;
}
}
+ else
+ {
+ error.SetErrorStringWithFormat("invalid variable path '%s'", var_expr_cstr);
+ }
return ValueObjectSP();
}
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 8546537..7990111 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -886,7 +886,9 @@
if (frame)
{
frame->CalculateExecutionContext(exe_ctx);
- result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr);
+ Error error;
+ const bool check_ptr_vs_member = true;
+ result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr, check_ptr_vs_member, error);
}
else if (m_process_sp)
{