summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2010-12-15 05:08:08 +0000
committerGreg Clayton <gclayton@apple.com>2010-12-15 05:08:08 +0000
commit54979cddda8e59afedbc66f2c3acf6cd8741306f (patch)
tree3bca3f8b22e2a168f1a4129e3cceb79ff2aa5f02 /lldb/source
parente893e2601e764644116563745810d223176abc5e (diff)
downloadbcm5719-llvm-54979cddda8e59afedbc66f2c3acf6cd8741306f.tar.gz
bcm5719-llvm-54979cddda8e59afedbc66f2c3acf6cd8741306f.zip
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. llvm-svn: 121841
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/API/SBTarget.cpp3
-rw-r--r--lldb/source/Commands/CommandObjectFrame.cpp187
-rw-r--r--lldb/source/Core/ValueObject.cpp101
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp68
-rw-r--r--lldb/source/Target/StackFrame.cpp310
-rw-r--r--lldb/source/Target/Target.cpp4
6 files changed, 313 insertions, 360 deletions
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index cae72479c7b..039c0ecdd51 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -50,7 +50,8 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// SBTarget constructor
//----------------------------------------------------------------------
-SBTarget::SBTarget ()
+SBTarget::SBTarget () :
+ m_opaque_sp ()
{
}
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index 1fecc88947e..2960362df4a 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -586,175 +586,36 @@ public:
}
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;
-
- }
-
- 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);
- }
+ var_sp->GetDeclaration ().DumpStopContext (&s, false);
+ s.PutCString (": ");
}
+ 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/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 60b1009ad7a..2f82d49bd0b 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -1203,10 +1203,11 @@ ValueObject::CreateConstantValue (ExecutionContextScope *exe_scope, const ConstS
}
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 @@ ValueObject::Dereference (ExecutionContextScope *exe_scope, Error *error_ptr)
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/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index cd725cac8aa..05643e63fc5 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -1901,7 +1901,10 @@ ClangASTContext::GetNumChildren (clang_type_t clang_qual_type, bool omit_empty_b
break;
}
break;
-
+
+ case clang::Type::Complex:
+ return 2;
+
case clang::Type::Record:
if (ClangASTType::IsDefined (clang_qual_type))
{
@@ -1995,12 +1998,15 @@ ClangASTContext::GetNumChildren (clang_type_t clang_qual_type, bool omit_empty_b
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 @@ ClangASTContext::GetNumChildren (clang_type_t clang_qual_type, bool omit_empty_b
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/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 20946532188..341954f2a11 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/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 @@ StackFrame::GetVariableList (bool get_file_globals)
}
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] == '*')
- {
- deref = true;
- var_expr++; // Skip the '*'
- }
- else 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)
{
- address_of = true;
- var_expr++; // Skip the '&'
- }
-
- std::string var_path (var_expr);
- size_t separator_idx = var_path.find_first_of(".-[");
+ // If first character is a '*', then show pointer contents
+ const char *var_expr = var_expr_cstr;
+ if (var_expr[0] == '*')
+ {
+ deref = true;
+ var_expr++; // Skip the '*'
+ }
+ else if (var_expr[0] == '&')
+ {
+ address_of = true;
+ var_expr++; // Skip the '&'
+ }
- 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);
+ std::string var_path (var_expr);
+ size_t separator_idx = var_path.find_first_of(".-[=+~|&^%#@!/?,<>{}");
+ StreamString var_expr_path_strm;
- VariableSP var_sp (variable_list->FindVariable(name_const_string));
- if (var_sp)
- {
- valobj_sp = GetValueObjectForFrameVariable (var_sp);
+ 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_path.erase (0, name_const_string.GetLength ());
- // We are dumping at least one child
- while (separator_idx != std::string::npos)
+ VariableSP var_sp (variable_list->FindVariable(name_const_string));
+ if (var_sp)
{
- // 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();
+ valobj_sp = GetValueObjectForFrameVariable (var_sp);
- var_path.erase (0, 1); // Remove the '-'
- // Fall through
- case '.':
+ 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)
{
- // 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"
+ case '-':
+ if (var_path.size() >= 2 && var_path[1] != '>')
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 == ']')
+ var_path.erase (0, 1); // Remove the '-'
+ // Fall through
+ case '.':
{
+ const bool expr_is_ptr = var_path[0] == '>';
- 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();
+ return ValueObjectSP();
- default:
- // Failure...
- 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());
- if (child_valobj_sp)
- valobj_sp = child_valobj_sp;
+ return ValueObjectSP();
+ }
+ }
- 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, NULL));
- valobj_sp = deref_valobj_sp;
}
- else if (address_of)
+ if (valobj_sp)
{
- ValueObjectSP address_of_valobj_sp (valobj_sp->AddressOf());
- valobj_sp = address_of_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;
+ }
+ else
+ {
+ 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/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 8546537b9a1..7990111aa43 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -886,7 +886,9 @@ Target::EvaluateExpression
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)
{
OpenPOWER on IntegriCloud