diff options
8 files changed, 125 insertions, 28 deletions
diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index a46ffcf4caf..dc9dcdfe495 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -581,7 +581,7 @@ public: lldb::ValueObjectSP GetSyntheticValue (lldb::SyntheticValueType use_synthetic); - bool + virtual bool HasSyntheticValue(); virtual lldb::ValueObjectSP diff --git a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h index ccfbacf9ead..0a1b0f157c4 100644 --- a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h +++ b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -65,6 +65,18 @@ public: IsInScope (); virtual bool + HasSyntheticValue() + { + return true; // we are our own synthetic value + } + + virtual void + CalculateSyntheticValue (lldb::SyntheticValueType use_synthetic) + { + m_synthetic_value = this; + } + + virtual bool IsDynamic () { if (m_parent) diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 010397739c3..fac774857fa 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -1161,6 +1161,7 @@ 69A01E1E1236C5D400C660B5 /* Mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mutex.cpp; sourceTree = "<group>"; }; 69A01E1F1236C5D400C660B5 /* Symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbols.cpp; sourceTree = "<group>"; }; 69A01E201236C5D400C660B5 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = "<group>"; }; + 94005E0313F438DF001EF42D /* python-wrapper.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-wrapper.swig"; sourceTree = "<group>"; }; 94031A9B13CF484600DCFF3C /* InputReaderEZ.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InputReaderEZ.h; path = include/lldb/Core/InputReaderEZ.h; sourceTree = "<group>"; }; 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputReaderEZ.cpp; path = source/Core/InputReaderEZ.cpp; sourceTree = "<group>"; }; 94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PriorityPointerPair.h; path = include/lldb/Utility/PriorityPointerPair.h; sourceTree = "<group>"; }; @@ -1734,6 +1735,7 @@ 266960611199F4230075C61A /* edit-swig-python-wrapper-file.py */, 266960621199F4230075C61A /* finish-swig-Python-lldb.sh */, 9A48A3A7124AAA5A00922451 /* python-extensions.swig */, + 94005E0313F438DF001EF42D /* python-wrapper.swig */, ); path = Python; sourceTree = "<group>"; diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 8d13293640e..08cbb1c4755 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -795,7 +795,7 @@ ScanBracketedRange(const char* var_name_begin, *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); *index_higher = *index_lower; if (log) - log->Printf("[%d] detected, high index is same",index_lower); + log->Printf("[%d] detected, high index is same", *index_lower); } else if (*close_bracket_position && *close_bracket_position < var_name_end) { @@ -803,7 +803,7 @@ ScanBracketedRange(const char* var_name_begin, *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); *index_higher = ::strtoul (*separator_position+1, &end, 0); if (log) - log->Printf("[%d-%d] detected",index_lower,index_higher); + log->Printf("[%d-%d] detected", *index_lower, *index_higher); } else { @@ -1044,7 +1044,7 @@ Debugger::FormatPrompt ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? ValueObject::eDereference : ValueObject::eNothing); ValueObject::GetValueForExpressionPathOptions options; - options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar(); + options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary; ValueObject* target = NULL; lldb::Format custom_format = eFormatInvalid; diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 80c8d5acd0f..fe27d712842 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -2032,13 +2032,28 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (!next_separator) // if no other separator just expand this last layer { child_name.SetCString (expression_cstr); - root = root->GetChildMemberWithName(child_name, true); - if (root.get()) // we know we are done, so just return + ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name, true); + + if (child_valobj_sp.get()) // we know we are done, so just return { *first_unparsed = '\0'; *reason_to_stop = ValueObject::eEndOfString; *final_result = ValueObject::ePlain; - return root; + return child_valobj_sp; + } + else if (options.m_no_synthetic_children == false) // let's try with synthetic children + { + child_valobj_sp = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildMemberWithName(child_name, true); + } + + // if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP, + // so we hit the "else" branch, and return an error + if(child_valobj_sp.get()) // if it worked, just return + { + *first_unparsed = '\0'; + *reason_to_stop = ValueObject::eEndOfString; + *final_result = ValueObject::ePlain; + return child_valobj_sp; } else { @@ -2051,9 +2066,24 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, else // other layers do expand { child_name.SetCStringWithLength(expression_cstr, next_separator - expression_cstr); - root = root->GetChildMemberWithName(child_name, true); - if (root.get()) // store the new root and move on + ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name, true); + if (child_valobj_sp.get()) // store the new root and move on + { + root = child_valobj_sp; + *first_unparsed = next_separator; + *final_result = ValueObject::ePlain; + continue; + } + else if (options.m_no_synthetic_children == false) // let's try with synthetic children + { + child_valobj_sp = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildMemberWithName(child_name, true); + } + + // if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP, + // so we hit the "else" branch, and return an error + if(child_valobj_sp.get()) // if it worked, move on { + root = child_valobj_sp; *first_unparsed = next_separator; *final_result = ValueObject::ePlain; continue; @@ -2236,7 +2266,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, return root; } } - else if (root->HasSyntheticValue() && options.m_no_synthetic_children) + else if (root->HasSyntheticValue() && options.m_no_synthetic_children == false) { root = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true); if (!root.get()) @@ -2246,6 +2276,12 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, *final_result = ValueObject::eInvalid; return ValueObjectSP(); } + else + { + *first_unparsed = end+1; // skip ] + *final_result = ValueObject::ePlain; + continue; + } } else { diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 9ce7590a2dd..299fdd1139c 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -641,23 +641,28 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true); if (!child_valobj_sp) { - // No child member with name "child_name" - valobj_sp->GetExpressionPath (var_expr_path_strm, false); - 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 + if (no_synth_child == false) + child_valobj_sp = valobj_sp->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildMemberWithName (child_name, true); + + if (no_synth_child || !child_valobj_sp) { - error.SetErrorStringWithFormat ("incomplete expression path after \"%s\" in \"%s\"", - var_expr_path_strm.GetString().c_str(), - var_expr_cstr); + // No child member with name "child_name" + valobj_sp->GetExpressionPath (var_expr_path_strm, false); + 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(); } - - return ValueObjectSP(); } // Remove the child name from the path var_path.erase(0, child_name.GetLength()); diff --git a/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py b/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py index 70994d41a2a..745800a70b1 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py @@ -194,6 +194,10 @@ class DataFormatterTestCase(TestBase): 'content = ', 'Process Name: a.out Process Id:']) + # check that access to synthetic children by name works + self.expect("frame variable str12->mutable", + substrs = ['(int) mutable = 0']) + # delete the synth and set a summary self.runCmd("type synth delete NSString") self.runCmd("type summary add -F CFString_SummaryProvider NSString") diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py index f06740e261f..ca1bc4e31e0 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py @@ -70,10 +70,34 @@ class DataFormatterTestCase(TestBase): 'fake_a = 16777216', 'a = 0']); - # check that we do not get the extra vars and that we cache results + # check that we do not get the extra vars self.expect("frame variable f00_1", matching=False, - substrs = ['looking for', - 'b = 1']); + substrs = ['b = 1']); + + # check access to members by name + self.expect('frame variable f00_1.fake_a', + substrs = ['16777216']) + + # check access to members by index + self.expect('frame variable f00_1[1]', + substrs = ['16777216']) + + # put synthetic children in summary in several combinations + self.runCmd("type summary add -f \"fake_a=${svar.fake_a}\" foo") + self.expect('frame variable f00_1', + substrs = ['fake_a=16777216']) + self.runCmd("type summary add -f \"fake_a=${var.fake_a}\" foo") + self.expect('frame variable f00_1', + substrs = ['fake_a=16777216']) + self.runCmd("type summary add -f \"fake_a=${var[1]}\" foo") + self.expect('frame variable f00_1', + substrs = ['fake_a=16777216']) + self.runCmd("type summary add -f \"fake_a=${svar[1]}\" foo") + self.expect('frame variable f00_1', + substrs = ['fake_a=16777216']) + + # clear the summary + self.runCmd("type summary delete foo") # check that the caching does not span beyond the stopoint self.runCmd("n") @@ -150,6 +174,20 @@ class DataFormatterTestCase(TestBase): '[2] = 123', '[3] = 1234', '}']) + + # check access to synthetic children + self.runCmd("type summary add -f \"item 0 is ${var[0]}\" std::int_vect int_vect") + self.expect('frame variable numbers', + substrs = ['item 0 is 1']); + + self.runCmd("type summary add -f \"item 0 is ${svar[0]}\" std::int_vect int_vect") + #import time + #time.sleep(19) + self.expect('frame variable numbers', + substrs = ['item 0 is 1']); + # move on with synths + self.runCmd("type summary delete std::int_vect") + self.runCmd("type summary delete int_vect") # add some more data self.runCmd("n");self.runCmd("n");self.runCmd("n"); |