[Lldb-commits] [lldb] r137097 - in /lldb/trunk: include/lldb/Core/ValueObject.h include/lldb/Target/StackFrame.h source/Core/ValueObject.cpp source/Symbol/ClangASTType.cpp source/Target/StackFrame.cpp source/Target/Target.cpp test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py
Enrico Granata
granata.enrico at gmail.com
Mon Aug 8 18:04:57 PDT 2011
Author: enrico
Date: Mon Aug 8 20:04:56 2011
New Revision: 137097
URL: http://llvm.org/viewvc/llvm-project?rev=137097&view=rev
Log:
Basic support for reading synthetic children by index:
if your datatype provides synthetic children, "frame variable object[index]" should now do the right thing
in cases where the above syntax would have been rejected before, i.e.
object is not a pointer nor an array (frame variable ignores potential overload of [])
object is a pointer to an Objective-C class (which cannot be dereferenced)
expression will still run operator[] if available and complain if it cannot do so
synthetic children by name do not work yet
Modified:
lldb/trunk/include/lldb/Core/ValueObject.h
lldb/trunk/include/lldb/Target/StackFrame.h
lldb/trunk/source/Core/ValueObject.cpp
lldb/trunk/source/Symbol/ClangASTType.cpp
lldb/trunk/source/Target/StackFrame.cpp
lldb/trunk/source/Target/Target.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py
Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Mon Aug 8 20:04:56 2011
@@ -122,13 +122,16 @@
bool m_check_dot_vs_arrow_syntax;
bool m_no_fragile_ivar;
bool m_allow_bitfields_syntax;
+ bool m_no_synthetic_children;
GetValueForExpressionPathOptions(bool dot = false,
bool no_ivar = false,
- bool bitfield = true) :
+ bool bitfield = true,
+ bool no_synth = false) :
m_check_dot_vs_arrow_syntax(dot),
m_no_fragile_ivar(no_ivar),
- m_allow_bitfields_syntax(bitfield)
+ m_allow_bitfields_syntax(bitfield),
+ m_no_synthetic_children(no_synth)
{
}
@@ -174,6 +177,20 @@
return *this;
}
+ GetValueForExpressionPathOptions&
+ DoAllowSyntheticChildren()
+ {
+ m_no_synthetic_children = false;
+ return *this;
+ }
+
+ GetValueForExpressionPathOptions&
+ DontAllowSyntheticChildren()
+ {
+ m_no_synthetic_children = true;
+ return *this;
+ }
+
static const GetValueForExpressionPathOptions
DefaultOptions()
{
@@ -565,6 +582,9 @@
lldb::ValueObjectSP
GetSyntheticValue (lldb::SyntheticValueType use_synthetic);
+ bool
+ HasSyntheticValue();
+
virtual lldb::ValueObjectSP
CreateConstantValue (const ConstString &name);
Modified: lldb/trunk/include/lldb/Target/StackFrame.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StackFrame.h?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StackFrame.h (original)
+++ lldb/trunk/include/lldb/Target/StackFrame.h Mon Aug 8 20:04:56 2011
@@ -32,8 +32,9 @@
public:
enum ExpressionPathOption
{
- eExpressionPathOptionCheckPtrVsMember = (1u << 0),
- eExpressionPathOptionsNoFragileObjcIvar = (1u << 1)
+ eExpressionPathOptionCheckPtrVsMember = (1u << 0),
+ eExpressionPathOptionsNoFragileObjcIvar = (1u << 1),
+ eExpressionPathOptionsNoSyntheticChildren = (1u << 2)
};
//------------------------------------------------------------------
// Constructors and Destructors
Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Mon Aug 8 20:04:56 2011
@@ -1668,6 +1668,22 @@
}
bool
+ValueObject::HasSyntheticValue()
+{
+ UpdateFormatsIfNeeded(m_last_format_mgr_dynamic);
+
+ if (m_last_synthetic_filter.get() == NULL)
+ return false;
+
+ CalculateSyntheticValue(lldb::eUseSyntheticFilter);
+
+ if (m_synthetic_value)
+ return true;
+ else
+ return false;
+}
+
+bool
ValueObject::GetBaseClassPath (Stream &s)
{
if (IsBaseClass())
@@ -2042,12 +2058,15 @@
{
if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray) && !root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if this is not a T[] nor a T*
{
- if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong!
+ if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar...
{
- *first_unparsed = expression_cstr;
- *reason_to_stop = ValueObject::eRangeOperatorInvalid;
- *final_result = ValueObject::eInvalid;
- return ValueObjectSP();
+ if (options.m_no_synthetic_children) // ...only chance left is synthetic
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eRangeOperatorInvalid;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
}
else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields
{
@@ -2117,6 +2136,9 @@
ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true);
if (!child_valobj_sp)
child_valobj_sp = root->GetSyntheticArrayMemberFromArray(index, true);
+ if (!child_valobj_sp)
+ if (root->HasSyntheticValue() && root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetNumChildren() > index)
+ child_valobj_sp = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true);
if (child_valobj_sp)
{
root = child_valobj_sp;
@@ -2154,7 +2176,19 @@
}
else
{
- root = root->GetSyntheticArrayMemberFromPointer(index, true);
+ if (ClangASTType::GetMinimumLanguage(root->GetClangAST(),
+ root->GetClangType()) == lldb::eLanguageTypeObjC
+ &&
+ ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(root->GetClangType())) == false
+ &&
+ root->HasSyntheticValue()
+ &&
+ options.m_no_synthetic_children == false)
+ {
+ root = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true);
+ }
+ else
+ root = root->GetSyntheticArrayMemberFromPointer(index, true);
if (!root.get())
{
*first_unparsed = expression_cstr;
@@ -2170,7 +2204,7 @@
}
}
}
- else /*if (ClangASTContext::IsScalarType(root_clang_type))*/
+ else if (ClangASTContext::IsScalarType(root_clang_type))
{
root = root->GetSyntheticBitFieldChild(index, index, true);
if (!root.get())
@@ -2188,6 +2222,24 @@
return root;
}
}
+ else if (root->HasSyntheticValue() && options.m_no_synthetic_children)
+ {
+ root = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
}
else // we have a low and a high index
{
Modified: lldb/trunk/source/Symbol/ClangASTType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTType.cpp?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTType.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTType.cpp Mon Aug 8 20:04:56 2011
@@ -115,6 +115,8 @@
ConstString
ClangASTType::GetConstTypeName ()
{
+ if (!ClangASTContext::GetCompleteType (this->m_ast, this->m_type))
+ return ConstString("<invalid>");
return GetConstTypeName (m_type);
}
Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Mon Aug 8 20:04:56 2011
@@ -525,6 +525,7 @@
{
const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0;
const bool no_fragile_ivar = (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
+ const bool no_synth_child = (options & eExpressionPathOptionsNoSyntheticChildren) != 0;
error.Clear();
bool deref = false;
bool address_of = false;
@@ -718,14 +719,55 @@
if (valobj_sp->IsPointerType ())
{
- child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
- if (!child_valobj_sp)
+ if (no_synth_child == false
+ &&
+ ClangASTType::GetMinimumLanguage(valobj_sp->GetClangAST(),
+ valobj_sp->GetClangType()) == lldb::eLanguageTypeObjC /* is ObjC pointer */
+ &&
+ ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(valobj_sp->GetClangType())) == false /* is not double-ptr */)
{
- valobj_sp->GetExpressionPath (var_expr_path_strm, false);
- 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());
+ // dereferencing ObjC variables is not valid.. so let's try and recur to synthetic children
+ lldb::ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(lldb::eUseSyntheticFilter);
+ if (synthetic.get() == NULL /* no synthetic */
+ || synthetic == valobj_sp) /* synthetic is the same as the original object */
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ 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
+ {
+ child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ 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
+ {
+ child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ 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))
@@ -757,10 +799,36 @@
}
else
{
- valobj_sp->GetExpressionPath (var_expr_path_strm, false);
- error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
- valobj_sp->GetTypeName().AsCString("<invalid type>"),
- var_expr_path_strm.GetString().c_str());
+ lldb::ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(lldb::eUseSyntheticFilter);
+ if (no_synth_child /* synthetic is forbidden */ ||
+ synthetic.get() == NULL /* no synthetic */
+ || synthetic == valobj_sp) /* synthetic is the same as the original object */
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ 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
+ {
+ child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ 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());
+ }
+ }
}
if (!child_valobj_sp)
Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Mon Aug 8 20:04:56 2011
@@ -1035,7 +1035,8 @@
frame->CalculateExecutionContext(exe_ctx);
Error error;
const uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsNoFragileObjcIvar;
+ StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
+ StackFrame::eExpressionPathOptionsNoSyntheticChildren;
lldb::VariableSP var_sp;
result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr,
use_dynamic,
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py Mon Aug 8 20:04:56 2011
@@ -164,6 +164,22 @@
'[5] = 123456',
'[6] = 1234567',
'}'])
+
+ # check access-by-index
+ self.expect("frame variable numbers[0]",
+ substrs = ['1']);
+ self.expect("frame variable numbers[1]",
+ substrs = ['12']);
+ self.expect("frame variable numbers[2]",
+ substrs = ['123']);
+ self.expect("frame variable numbers[3]",
+ substrs = ['1234']);
+
+ # but check that expression does not rely on us
+ # (when expression gets to call into STL code correctly, we will have to find
+ # another way to check this)
+ self.expect("expression numbers[6]", matching=False, error=True,
+ substrs = ['1234567'])
# clear out the vector and see that we do the right thing once again
self.runCmd("n")
@@ -202,6 +218,18 @@
self.expect("frame variable strings",
substrs = ['vector has 4 items'])
+
+ # check access-by-index
+ self.expect("frame variable strings[0]",
+ substrs = ['goofy']);
+ self.expect("frame variable strings[1]",
+ substrs = ['is']);
+
+ # but check that expression does not rely on us
+ # (when expression gets to call into STL code correctly, we will have to find
+ # another way to check this)
+ self.expect("expression strings[0]", matching=False, error=True,
+ substrs = ['goofy'])
self.runCmd("n")
@@ -255,6 +283,16 @@
'0x0abcdef0',
'[5] =',
'0x0cab0cab'])
+
+ # check access-by-index
+ self.expect("frame variable numbers_list[0]",
+ substrs = ['0x12345678']);
+ self.expect("frame variable numbers_list[1]",
+ substrs = ['0x11223344']);
+
+ # but check that expression does not rely on us
+ self.expect("expression numbers_list[0]", matching=False, error=True,
+ substrs = ['0x12345678'])
self.runCmd("n")
@@ -298,6 +336,16 @@
'[1] = \"is\"',
'[2] = \"smart\"',
'[3] = \"!!!\"'])
+
+ # check access-by-index
+ self.expect("frame variable text_list[0]",
+ substrs = ['goofy']);
+ self.expect("frame variable text_list[3]",
+ substrs = ['!!!']);
+
+ # but check that expression does not rely on us
+ self.expect("expression text_list[0]", matching=False, error=True,
+ substrs = ['goofy'])
# now std::map<K,V>
# also take a chance to test regex synth here
@@ -347,6 +395,18 @@
'[7] = {',
'first = 7',
'second = 1'])
+
+ # check access-by-index
+ self.expect("frame variable ii[0]",
+ substrs = ['first = 0',
+ 'second = 0']);
+ self.expect("frame variable ii[3]",
+ substrs = ['first =',
+ 'second =']);
+
+ # but check that expression does not rely on us
+ self.expect("expression ii[0]", matching=False, error=True,
+ substrs = ['first = 0'])
self.runCmd("n")
@@ -391,6 +451,15 @@
'[4] = ',
'first = \"four\"',
'second = 4'])
+
+ # check access-by-index
+ self.expect("frame variable si[0]",
+ substrs = ['first = ', 'four',
+ 'second = 4']);
+
+ # but check that expression does not rely on us
+ self.expect("expression si[0]", matching=False, error=True,
+ substrs = ['first = ', 'zero'])
self.runCmd("n")
@@ -424,6 +493,15 @@
'[3] = ',
'second = \"!!!\"',
'first = 3'])
+
+ # check access-by-index
+ self.expect("frame variable is[0]",
+ substrs = ['first = ', '0',
+ 'second =', 'goofy']);
+
+ # but check that expression does not rely on us
+ self.expect("expression is[0]", matching=False, error=True,
+ substrs = ['first = ', 'goofy'])
self.runCmd("n")
@@ -457,6 +535,14 @@
'[3] = ',
'second = \"..is always a Mac!\"',
'first = \"a Mac..\"'])
+
+ # check access-by-index
+ self.expect("frame variable ss[3]",
+ substrs = ['gatto', 'cat']);
+
+ # but check that expression does not rely on us
+ self.expect("expression ss[3]", matching=False, error=True,
+ substrs = ['gatto'])
self.runCmd("n")
More information about the lldb-commits
mailing list