summaryrefslogtreecommitdiffstats
path: root/lldb/source/Target/StackFrame.cpp
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/Target/StackFrame.cpp
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/Target/StackFrame.cpp')
-rw-r--r--lldb/source/Target/StackFrame.cpp310
1 files changed, 195 insertions, 115 deletions
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();
}
OpenPOWER on IntegriCloud