diff options
author | Enrico Granata <egranata@apple.com> | 2014-12-09 21:41:16 +0000 |
---|---|---|
committer | Enrico Granata <egranata@apple.com> | 2014-12-09 21:41:16 +0000 |
commit | 986fa5f4eb037877fd470770be0a7ca9ebeac9ca (patch) | |
tree | 576063bc56686401046bf959865b97cee01d2dab | |
parent | 93e9cf8aa43545d5ebe7ea10642eb19ec458554d (diff) | |
download | bcm5719-llvm-986fa5f4eb037877fd470770be0a7ca9ebeac9ca.tar.gz bcm5719-llvm-986fa5f4eb037877fd470770be0a7ca9ebeac9ca.zip |
Extend ValueObject::GetExpressionPath() to do something reasonable for synthetic children
Because of the way they are created, synthetic children cannot (in general) have a sane expression path
A solution to this would be letting the parent front-end generate expression paths for its children
Doing so requires a significant amount of refactoring, and might not always lead to better results (esp. w.r.t. C++ templates)
This commit takes a simpler approach:
- if a synthetic child is of pointer type and it's a target pointer, then emit *((T)value)
- if a synthetic child is a non-pointer, but its location is in the target, then emit *((T*)loadAddr)
- if a synthetic child has a value, emit ((T)value)
- else, don't emit anything
Fixes rdar://18442386
llvm-svn: 223836
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 40 | ||||
-rw-r--r-- | lldb/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py | 3 | ||||
-rw-r--r-- | lldb/test/python_api/exprpath_synthetic/main.mm | 20 |
3 files changed, 63 insertions, 0 deletions
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 5487b601655..33e968d1c1b 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -2540,6 +2540,46 @@ ValueObject::IsBaseClass (uint32_t& depth) void ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat) { + // synthetic children do not actually "exist" as part of the hierarchy, and sometimes they are consed up in ways + // that don't make sense from an underlying language/API standpoint. So, use a special code path here to return + // something that can hopefully be used in expression + if (m_is_synthetic_children_generated) + { + UpdateValueIfNeeded(); + + if (m_value.GetValueType() == Value::eValueTypeLoadAddress) + { + if (IsPointerOrReferenceType()) + { + s.Printf("((%s)0x%" PRIx64 ")", + GetTypeName().AsCString("void"), + GetValueAsUnsigned(0)); + return; + } + else + { + uint64_t load_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + if (load_addr != LLDB_INVALID_ADDRESS) + { + s.Printf("(*( (%s *)0x%" PRIx64 "))", + GetTypeName().AsCString("void"), + load_addr); + return; + } + } + } + + if (CanProvideValue()) + { + s.Printf("((%s)%s)", + GetTypeName().AsCString("void"), + GetValueAsCString()); + return; + } + + return; + } + const bool is_deref_of_parent = IsDereferenceOfParent (); if (is_deref_of_parent && epformat == eGetExpressionPathFormatDereferencePointers) diff --git a/lldb/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py b/lldb/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py new file mode 100644 index 00000000000..a70d2ca7414 --- /dev/null +++ b/lldb/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py @@ -0,0 +1,3 @@ +import lldbinline + +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/lldb/test/python_api/exprpath_synthetic/main.mm b/lldb/test/python_api/exprpath_synthetic/main.mm new file mode 100644 index 00000000000..f7383a5a14d --- /dev/null +++ b/lldb/test/python_api/exprpath_synthetic/main.mm @@ -0,0 +1,20 @@ +//===-- main.mm --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#import <Cocoa/Cocoa.h> +#include <vector> + +int main (int argc, char const *argv[]) +{ + std::vector<int> v{1,2,3,4,5}; + NSArray *a = @[@"Hello",@"World",@"From Me"]; + return 0; //% v = self.frame().FindVariable("v"); v0 = v.GetChildAtIndex(0); s = lldb.SBStream(); v0.GetExpressionPath(s); + //% self.runCmd("expr %s = 12" % s.GetData()); self.assertTrue(v0.GetValueAsUnsigned() == 12, "value change via expr failed") + //% a = self.frame().FindVariable("a"); a1 = a.GetChildAtIndex(1); s = lldb.SBStream(); a1.GetExpressionPath(s); + //% self.expect("po %s" % s.GetData(), substrs = ["World"]) +} |