diff options
author | Greg Clayton <gclayton@apple.com> | 2010-10-14 22:52:14 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2010-10-14 22:52:14 +0000 |
commit | 8f92f0a35cba08ca0b4ff83b062494bc9d81ebe0 (patch) | |
tree | 2eadcc035d4e643d3ede63794a1b6a85a60ccf95 /lldb/source/Core/ValueObject.cpp | |
parent | 10169b94cfe6838f881339f1944891f6d8451174 (diff) | |
download | bcm5719-llvm-8f92f0a35cba08ca0b4ff83b062494bc9d81ebe0.tar.gz bcm5719-llvm-8f92f0a35cba08ca0b4ff83b062494bc9d81ebe0.zip |
Fixed an expression parsing issue where if you were stopped somewhere without
debug information and you evaluated an expression, a crash would occur as a
result of an unchecked pointer.
Added the ability to get the expression path for a ValueObject. For a rectangle
point child "x" the expression path would be something like: "rect.top_left.x".
This will allow GUI and command lines to get ahold of the expression path for
a value object without having to explicitly know about the hierarchy. This
means the ValueObject base class now has a "ValueObject *m_parent;" member.
All ValueObject subclasses now correctly track their lineage and are able
to provide value expression paths as well.
Added a new "--flat" option to the "frame variable" to allow for flat variable
output. An example of the current and new outputs:
(lldb) frame variable
argc = 1
argv = 0x00007fff5fbffe80
pt = {
x = 2
y = 3
}
rect = {
bottom_left = {
x = 1
y = 2
}
top_right = {
x = 3
y = 4
}
}
(lldb) frame variable --flat
argc = 1
argv = 0x00007fff5fbffe80
pt.x = 2
pt.y = 3
rect.bottom_left.x = 1
rect.bottom_left.y = 2
rect.top_right.x = 3
rect.top_right.y = 4
As you can see when there is a lot of hierarchy it can help flatten things out.
Also if you want to use a member in an expression, you can copy the text from
the "--flat" output and not have to piece it together manually. This can help
when you want to use parts of the STL in expressions:
(lldb) frame variable --flat
argc = 1
argv = 0x00007fff5fbffea8
hello_world._M_dataplus._M_p = 0x0000000000000000
(lldb) expr hello_world._M_dataplus._M_p[0] == '\0'
llvm-svn: 116532
Diffstat (limited to 'lldb/source/Core/ValueObject.cpp')
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 230 |
1 files changed, 162 insertions, 68 deletions
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index bd613ba7b2c..c8c5f3362fe 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -42,8 +42,9 @@ static lldb::user_id_t g_value_obj_uid = 0; //---------------------------------------------------------------------- // ValueObject constructor //---------------------------------------------------------------------- -ValueObject::ValueObject () : +ValueObject::ValueObject (ValueObject *parent) : UserID (++g_value_obj_uid), // Unique identifier for every value object + m_parent (parent), m_update_id (0), // Value object lists always start at 1, value objects start at zero m_name (), m_data (), @@ -354,6 +355,7 @@ ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int3 int32_t child_byte_offset = 0; uint32_t child_bitfield_bit_size = 0; uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; const bool transparent_pointers = synthetic_array_member == false; clang::ASTContext *clang_ast = GetClangAST(); void *clang_type = GetClangType(); @@ -368,7 +370,8 @@ ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int3 child_byte_size, child_byte_offset, child_bitfield_bit_size, - child_bitfield_bit_offset); + child_bitfield_bit_offset, + child_is_base_class); if (child_clang_type) { if (synthetic_index) @@ -385,7 +388,8 @@ ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int3 child_byte_size, child_byte_offset, child_bitfield_bit_size, - child_bitfield_bit_offset)); + child_bitfield_bit_offset, + child_is_base_class)); } return valobj_sp; } @@ -863,6 +867,46 @@ ValueObject::SetDynamicValue () void +ValueObject::GetExpressionPath (Stream &s) +{ + if (m_parent) + { + m_parent->GetExpressionPath (s); + clang_type_t parent_clang_type = m_parent->GetClangType(); + if (parent_clang_type) + { + if (ClangASTContext::IsPointerType(parent_clang_type)) + { + s.PutCString("->"); + } + else if (ClangASTContext::IsAggregateType (parent_clang_type)) + { + if (ClangASTContext::IsArrayType (parent_clang_type) == false && + m_parent->IsBaseClass() == false) + s.PutChar('.'); + } + } + } + + if (IsBaseClass()) + { + clang_type_t clang_type = GetClangType(); + std::string cxx_class_name; + if (ClangASTContext::GetCXXClassName (clang_type, cxx_class_name)) + { + s << cxx_class_name.c_str() << "::"; + } + } + else + { + const char *name = GetName().AsCString(); + if (name) + s.PutCString(name); + } +} + + +void ValueObject::DumpValueObject ( Stream &s, @@ -875,33 +919,59 @@ ValueObject::DumpValueObject bool show_types, bool show_location, bool use_objc, - bool scope_already_checked + bool scope_already_checked, + bool flat_output ) { if (valobj) { //const char *loc_cstr = valobj->GetLocationAsCString(); - if (show_location) + clang_type_t clang_type = valobj->GetClangType(); + + const Flags type_info_flags (ClangASTContext::GetTypeInfoMask (clang_type)); + const char *err_cstr = NULL; + const bool has_children = type_info_flags.IsSet (ClangASTContext::eTypeHasChildren); + const bool has_value = type_info_flags.IsSet (ClangASTContext::eTypeHasValue); + + const bool print_valobj = flat_output == false || has_value; + + if (print_valobj) { - s.Printf("%s: ", valobj->GetLocationAsCString(exe_scope)); - } + if (show_location) + { + s.Printf("%s: ", valobj->GetLocationAsCString(exe_scope)); + } - s.Indent(); + s.Indent(); - if (show_types) - s.Printf("(%s) ", valobj->GetTypeName().AsCString()); + if (show_types) + s.Printf("(%s) ", valobj->GetTypeName().AsCString()); - const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString(""); - s.Printf ("%s = ", name_cstr); - if (!scope_already_checked && !valobj->IsInScope(exe_scope->CalculateStackFrame())) - { - s.PutCString("error: out of scope"); - return; + if (flat_output) + { + valobj->GetExpressionPath(s); + s.PutCString(" ="); + } + else + { + const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString(""); + s.Printf ("%s =", name_cstr); + } + + if (!scope_already_checked && !valobj->IsInScope(exe_scope->CalculateStackFrame())) + { + err_cstr = "error: out of scope"; + } } - const char *val_cstr = valobj->GetValueAsCString(exe_scope); - const char *err_cstr = valobj->GetError().AsCString(); + const char *val_cstr = NULL; + + if (err_cstr == NULL) + { + val_cstr = valobj->GetValueAsCString(exe_scope); + err_cstr = valobj->GetError().AsCString(); + } if (err_cstr) { @@ -909,75 +979,99 @@ ValueObject::DumpValueObject } else { - const char *sum_cstr = valobj->GetSummaryAsCString(exe_scope); - - const bool is_aggregate = ClangASTContext::IsAggregateType (valobj->GetClangType()); + if (print_valobj) + { + const char *sum_cstr = valobj->GetSummaryAsCString(exe_scope); - if (val_cstr) - s.PutCString(val_cstr); + if (val_cstr) + s.Printf(" %s", val_cstr); - if (sum_cstr) - s.Printf(" %s", sum_cstr); - - if (use_objc) - { - const char *object_desc = valobj->GetObjectDescription(exe_scope); - if (object_desc) - s.Printf("\n%s\n", object_desc); - else - s.Printf ("No description available.\n"); - return; + if (sum_cstr) + s.Printf(" %s", sum_cstr); + + if (use_objc) + { + const char *object_desc = valobj->GetObjectDescription(exe_scope); + if (object_desc) + s.Printf(" %s\n", object_desc); + else + s.Printf ("No description available.\n"); + return; + } } - if (curr_depth < max_depth) { - if (is_aggregate) - s.PutChar('{'); - - bool is_ptr_or_ref = ClangASTContext::IsPointerOrReferenceType (valobj->GetClangType()); + bool is_ptr_or_ref = type_info_flags.IsSet (ClangASTContext::eTypeIsPointer | ClangASTContext::eTypeIsReference); - if (is_ptr_or_ref && ptr_depth == 0) - return; - - const uint32_t num_children = valobj->GetNumChildren(); - if (num_children) + if (!is_ptr_or_ref || ptr_depth > 0) { - s.IndentMore(); - for (uint32_t idx=0; idx<num_children; ++idx) + const uint32_t num_children = valobj->GetNumChildren(); + if (num_children) { - ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true)); - if (child_sp.get()) + if (flat_output) { - s.EOL(); - DumpValueObject (s, - exe_scope, - child_sp.get(), - NULL, - is_ptr_or_ref ? ptr_depth - 1 : ptr_depth, - curr_depth + 1, - max_depth, - show_types, - show_location, - false, - true); - if (idx + 1 < num_children) - s.PutChar(','); + if (print_valobj) + s.EOL(); + } + else + { + if (print_valobj) + s.PutCString(" {\n"); + s.IndentMore(); + } + + for (uint32_t idx=0; idx<num_children; ++idx) + { + ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true)); + if (child_sp.get()) + { + DumpValueObject (s, + exe_scope, + child_sp.get(), + NULL, + is_ptr_or_ref ? ptr_depth - 1 : ptr_depth, + curr_depth + 1, + max_depth, + show_types, + show_location, + false, + true, + flat_output); + } + } + + if (!flat_output) + { + s.IndentLess(); + s.Indent("}\n"); } } - s.IndentLess(); + else if (has_children) + { + // Aggregate, no children... + if (print_valobj) + s.PutCString("{}\n"); + } + else + { + if (print_valobj) + s.EOL(); + } + } - if (is_aggregate) - { + else + { + // We printed a pointer, but we are stopping and not printing + // and children of this pointer... s.EOL(); - s.Indent("}"); } } else { - if (is_aggregate) + if (has_children && print_valobj) { - s.PutCString("{...}"); + s.PutCString("{...}\n"); } } } |