forked from OSchip/llvm-project
The data formatters for NSArray, NSDictionary and (only partially) NSSet contain logic to inspect the objects without running code.
However, they also contain fallback logic that - in cases where LLDB can't recognize the specific subclass - actually does run code in order to inspect those objects. The argument for this logic was that these data types are critical enough that the risk of getting it wrong is outweighed by the advantage of always providing accurate child information. Practical experience however shows that "po" - a code running data-inspection command - is quite frequently used, and not considered burdensome by users. As such, this makes the code-running fallback in the data formatters a risk that carries very little actual reward. Also, unlike the time this code was originally written, we now have accurate class information for Objective-C, and thus we are less likely to improperly identify classes. This commit removes support for the code-running fallback, and aligns the data formatters for NSArray, NSDictionary and NSSet to the general no-code-running behavior of other data formatters. While it is possible for us to add support for some subclasses that are now no longer covered by static inspection alone, this is beyond the scope of this commit. llvm-svn: 260664
This commit is contained in:
parent
47134196fc
commit
2543d29048
|
@ -214,18 +214,13 @@ class ObjCDataFormatterTestCase(TestBase):
|
|||
'(NSNumber *) num_at4 = ',' (double)-12.5'])
|
||||
|
||||
def nscontainers_data_formatter_commands(self):
|
||||
self.expect('frame variable newArray newDictionary newMutableDictionary cfdict_ref mutable_dict_ref cfarray_ref mutable_array_ref',
|
||||
self.expect('frame variable newArray newDictionary newMutableDictionary cfarray_ref mutable_array_ref',
|
||||
substrs = ['(NSArray *) newArray = ','@"50 elements"',
|
||||
'(NSDictionary *) newDictionary = ',' 12 key/value pairs',
|
||||
'(NSDictionary *) newMutableDictionary = ',' 21 key/value pairs',
|
||||
'(CFDictionaryRef) cfdict_ref = ','3 key/value pairs',
|
||||
'(CFMutableDictionaryRef) mutable_dict_ref = ','12 key/value pairs',
|
||||
'(CFArrayRef) cfarray_ref = ','@"3 elements"',
|
||||
'(CFMutableArrayRef) mutable_array_ref = ','@"11 elements"'])
|
||||
|
||||
self.expect('frame variable nscounted_set',
|
||||
substrs = ['(NSCountedSet *) nscounted_set = ','5 elements'])
|
||||
|
||||
self.expect('frame variable iset1 iset2 imset',
|
||||
substrs = ['4 indexes','512 indexes','10 indexes'])
|
||||
|
||||
|
|
|
@ -415,41 +415,6 @@ int main (int argc, const char * argv[])
|
|||
|
||||
CFStringRef cfstring_ref = CFSTR("HELLO WORLD");
|
||||
|
||||
|
||||
CFSetRef set_ref = CFSetCreate(NULL, data_set, 3, NULL);
|
||||
|
||||
CFMutableSetRef mutable_set_ref = CFSetCreateMutable(NULL, 5, NULL);
|
||||
|
||||
CFSetAddValue(mutable_set_ref, str1);
|
||||
CFSetAddValue(mutable_set_ref, str2);
|
||||
CFSetAddValue(mutable_set_ref, str3);
|
||||
CFSetAddValue(mutable_set_ref, str4);
|
||||
CFSetAddValue(mutable_set_ref, str5);
|
||||
CFSetAddValue(mutable_set_ref, str6);
|
||||
CFSetAddValue(mutable_set_ref, str7);
|
||||
CFSetAddValue(mutable_set_ref, str8);
|
||||
CFSetAddValue(mutable_set_ref, str9);
|
||||
CFSetAddValue(mutable_set_ref, str10);
|
||||
CFSetAddValue(mutable_set_ref, str11);
|
||||
CFSetAddValue(mutable_set_ref, str12);
|
||||
|
||||
|
||||
CFDictionaryRef cfdict_ref = CFDictionaryCreate(NULL, data_set, data_set, 3, NULL, NULL);
|
||||
CFMutableDictionaryRef mutable_dict_ref = CFDictionaryCreateMutable(NULL, 16, NULL, NULL);
|
||||
|
||||
CFDictionarySetValue(mutable_dict_ref, str1, str1);
|
||||
CFDictionarySetValue(mutable_dict_ref, str2, str2);
|
||||
CFDictionarySetValue(mutable_dict_ref, str3, str3);
|
||||
CFDictionarySetValue(mutable_dict_ref, str4, str1);
|
||||
CFDictionarySetValue(mutable_dict_ref, str5, str2);
|
||||
CFDictionarySetValue(mutable_dict_ref, str6, str3);
|
||||
CFDictionarySetValue(mutable_dict_ref, str7, str1);
|
||||
CFDictionarySetValue(mutable_dict_ref, str8, str2);
|
||||
CFDictionarySetValue(mutable_dict_ref, str9, str3);
|
||||
CFDictionarySetValue(mutable_dict_ref, str10, str1);
|
||||
CFDictionarySetValue(mutable_dict_ref, str11, str2);
|
||||
CFDictionarySetValue(mutable_dict_ref, str12, str3);
|
||||
|
||||
CFArrayRef cfarray_ref = CFArrayCreate(NULL, data_set, 3, NULL);
|
||||
CFMutableArrayRef mutable_array_ref = CFArrayCreateMutable(NULL, 16, NULL);
|
||||
|
||||
|
@ -556,16 +521,6 @@ int main (int argc, const char * argv[])
|
|||
CFAbsoluteTime date3_abs = CFDateGetAbsoluteTime(date3);
|
||||
CFAbsoluteTime date4_abs = CFDateGetAbsoluteTime(date4);
|
||||
|
||||
NSCountedSet *nscounted_set = [[NSCountedSet alloc] initWithCapacity:5];
|
||||
|
||||
[nscounted_set addObject:str0];
|
||||
[nscounted_set addObject:str1];
|
||||
[nscounted_set addObject:str0];
|
||||
[nscounted_set addObject:str0];
|
||||
[nscounted_set addObject:@"foo1"];
|
||||
[nscounted_set addObject:@"foo2"];
|
||||
[nscounted_set addObject:@"foo3"];
|
||||
|
||||
NSIndexSet *iset1 = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(1, 4)];
|
||||
NSIndexSet *iset2 = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(1, 512)];
|
||||
|
||||
|
|
|
@ -69,10 +69,6 @@ class DataFormatterOneIsSingularTestCase(TestBase):
|
|||
substrs = ['@"1 value"'])
|
||||
self.expect('frame variable mutable_bag_ref', matching=False,
|
||||
substrs = ['1 values'])
|
||||
self.expect('frame variable nscounted_set',
|
||||
substrs = ['1 element'])
|
||||
self.expect('frame variable nscounted_set', matching=False,
|
||||
substrs = ['1 elements'])
|
||||
self.expect('frame variable imset',
|
||||
substrs = ['1 index'])
|
||||
self.expect('frame variable imset', matching=False,
|
||||
|
@ -81,10 +77,6 @@ class DataFormatterOneIsSingularTestCase(TestBase):
|
|||
substrs = ['@"1 item"'])
|
||||
self.expect('frame variable binheap_ref', matching=False,
|
||||
substrs = ['1 items'])
|
||||
self.expect('frame variable nsset',
|
||||
substrs = ['1 element'])
|
||||
self.expect('frame variable nsset', matching=False,
|
||||
substrs = ['1 elements'])
|
||||
self.expect('frame variable immutableData',
|
||||
substrs = ['1 byte'])
|
||||
self.expect('frame variable immutableData', matching=False,
|
||||
|
|
|
@ -22,17 +22,12 @@ int main (int argc, const char * argv[])
|
|||
CFMutableBagRef mutable_bag_ref = CFBagCreateMutable(NULL, 15, NULL);
|
||||
CFBagSetValue(mutable_bag_ref, CFSTR("Hello world"));
|
||||
|
||||
NSCountedSet *nscounted_set = [[NSCountedSet alloc] initWithCapacity:5];
|
||||
[nscounted_set addObject:@"foo"];
|
||||
|
||||
NSMutableIndexSet *imset = [[NSMutableIndexSet alloc] init];
|
||||
[imset addIndex:4];
|
||||
|
||||
CFBinaryHeapRef binheap_ref = CFBinaryHeapCreate(NULL, 15, &kCFStringBinaryHeapCallBacks, NULL);
|
||||
CFBinaryHeapAddValue(binheap_ref, CFSTR("Hello world"));
|
||||
|
||||
NSSet* nsset = [[NSSet alloc] initWithObjects:@"foo",nil];
|
||||
|
||||
NSData *immutableData = [[NSData alloc] initWithBytes:"HELLO" length:1];
|
||||
|
||||
|
||||
|
|
|
@ -227,29 +227,6 @@ namespace lldb_private {
|
|||
size_t
|
||||
GetIndexOfChildWithName(const ConstString &name) override;
|
||||
};
|
||||
|
||||
class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
|
||||
{
|
||||
public:
|
||||
NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
|
||||
|
||||
~NSArrayCodeRunningSyntheticFrontEnd() override = default;
|
||||
|
||||
size_t
|
||||
CalculateNumChildren() override;
|
||||
|
||||
lldb::ValueObjectSP
|
||||
GetChildAtIndex(size_t idx) override;
|
||||
|
||||
bool
|
||||
Update() override;
|
||||
|
||||
bool
|
||||
MightHaveChildren() override;
|
||||
|
||||
size_t
|
||||
GetIndexOfChildWithName(const ConstString &name) override;
|
||||
};
|
||||
} // namespace formatters
|
||||
} // namespace lldb_private
|
||||
|
||||
|
@ -312,10 +289,7 @@ lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& s
|
|||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string prefix,suffix;
|
||||
if (Language* language = Language::FindPlugin(options.GetLanguage()))
|
||||
|
@ -740,53 +714,6 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCre
|
|||
else
|
||||
return (new NSArrayMSyntheticFrontEnd_109(valobj_sp));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
|
||||
}
|
||||
}
|
||||
|
||||
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get())
|
||||
{}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
uint64_t count = 0;
|
||||
if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
StreamString idx_name;
|
||||
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
|
||||
lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
|
||||
if (valobj_sp)
|
||||
{
|
||||
valobj_sp->SetPreferredDisplayLanguage(m_backend.GetPreferredDisplayLanguage());
|
||||
valobj_sp->SetName(ConstString(idx_name.GetData()));
|
||||
}
|
||||
return valobj_sp;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
return 0;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -190,29 +190,6 @@ namespace lldb_private {
|
|||
CompilerType m_pair_type;
|
||||
std::vector<DictionaryItemDescriptor> m_children;
|
||||
};
|
||||
|
||||
class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
|
||||
{
|
||||
public:
|
||||
NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
|
||||
|
||||
~NSDictionaryCodeRunningSyntheticFrontEnd() override = default;
|
||||
|
||||
size_t
|
||||
CalculateNumChildren() override;
|
||||
|
||||
lldb::ValueObjectSP
|
||||
GetChildAtIndex(size_t idx) override;
|
||||
|
||||
bool
|
||||
Update() override;
|
||||
|
||||
bool
|
||||
MightHaveChildren() override;
|
||||
|
||||
size_t
|
||||
GetIndexOfChildWithName(const ConstString &name) override;
|
||||
};
|
||||
} // namespace formatters
|
||||
} // namespace lldb_private
|
||||
|
||||
|
@ -282,7 +259,7 @@ lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stre
|
|||
auto iter = map.find(class_name_cs), end = map.end();
|
||||
if (iter != end)
|
||||
return iter->second(valobj, stream, options);
|
||||
if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -350,64 +327,9 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontE
|
|||
auto iter = map.find(class_name_cs), end = map.end();
|
||||
if (iter != end)
|
||||
return iter->second(synth, valobj_sp);
|
||||
return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp));
|
||||
}
|
||||
}
|
||||
|
||||
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get())
|
||||
{}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
uint64_t count = 0;
|
||||
if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
StreamString idx_name;
|
||||
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
|
||||
StreamString key_fetcher_expr;
|
||||
key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%" PRIu64 "]", m_backend.GetPointerValue(), (uint64_t)idx);
|
||||
StreamString value_fetcher_expr;
|
||||
value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData());
|
||||
StreamString object_fetcher_expr;
|
||||
object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData());
|
||||
lldb::ValueObjectSP child_sp;
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetKeepInMemory(true);
|
||||
options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
|
||||
options.SetResultIsInternal(true);
|
||||
m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(),
|
||||
GetViableFrame(m_backend.GetTargetSP().get()),
|
||||
child_sp,
|
||||
options);
|
||||
if (child_sp)
|
||||
child_sp->SetName(ConstString(idx_name.GetData()));
|
||||
return child_sp;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
return 0;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
|
|
|
@ -277,7 +277,7 @@ lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& str
|
|||
auto iter = map.find(class_name_cs), end = map.end();
|
||||
if (iter != end)
|
||||
return iter->second(valobj, stream, options);
|
||||
if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -349,7 +349,7 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreat
|
|||
auto iter = map.find(class_name_cs), end = map.end();
|
||||
if (iter != end)
|
||||
return iter->second(synth, valobj_sp);
|
||||
return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue