mib created this revision. mib added reviewers: friss, davide, jingham. mib added a project: LLDB. Herald added a subscriber: lldb-commits.
This patch improves data formatting for CFDictionaryRef and CFSetRef. It uses the same data-formatter as NSCFDictionaries and NSCFSets introduced previously (D78396 <https://reviews.llvm.org/D78396>) but did require some adjustments in Core::ValueObject. Since the "Ref" types are opaque pointers to the actual CF containers, if the value object has a synthetic value, lldb will create an empty record type to create the new ValueObjectChild needed to dereference the original ValueObject. This allows the "Ref" types to behaves the same as CF containers when used with the `frame variable` command, the SBAPI or in Xcode's variable inspector. rdar://53104287 Signed-off-by: Med Ismail Bennani <medismail.benn...@gmail.com> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D79554 Files: lldb/source/Core/ValueObject.cpp lldb/source/Plugins/Language/ObjC/NSSet.cpp lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
Index: lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m =================================================================== --- lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m +++ lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m @@ -482,8 +482,7 @@ CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 2, nil, nil)); NSDictionary *nscfDictionary = CFBridgingRelease( CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 4, nil, nil)); - CFDictionaryRef cfDictionaryRef = - CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 3, nil, nil); + CFDictionaryRef cfDictionaryRef = (__bridge CFDictionaryRef)nsDictionary; NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"hello world from foo" @@ -542,6 +541,7 @@ [nsmutableset addObject:str4]; NSSet *nscfSet = CFBridgingRelease(CFSetCreate(nil, (void *)cfValues, 2, nil)); + CFSetRef cfSetRef = (__bridge CFSetRef)nscfSet; CFDataRef data_ref = CFDataCreate(kCFAllocatorDefault, [immutableData bytes], 5); Index: lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py =================================================================== --- lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py +++ lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py @@ -32,7 +32,7 @@ '(NSDictionary *) nscfDictionary = ', ' 4 key/value pairs', '(CFDictionaryRef) cfDictionaryRef = ', - ' 3 key/value pairs', + ' 2 key/value pairs', '(NSDictionary *) newMutableDictionary = ', ' 21 key/value pairs', '(CFArrayRef) cfarray_ref = ', @@ -55,12 +55,25 @@ 'value = 0x.* @"quux"', ]) + + self.expect( + 'frame variable -d run-target *cfDictionaryRef', + patterns=[ + '\(CFDictionaryRef\) \*cfDictionaryRef =', + 'key = 0x.* @"foo"', + 'value = 0x.* @"foo"', + 'key = 0x.* @"bar"', + 'value = 0x.* @"bar"', + ]) + self.expect( - 'frame var nscfSet', + 'frame var nscfSet cfSetRef', substrs=[ '(NSSet *) nscfSet = ', '2 elements', + '(CFSetRef) cfSetRef = ', + '2 elements', ]) self.expect( @@ -70,6 +83,14 @@ '\[0\] = 0x.* @".*"', '\[1\] = 0x.* @".*"', ]) + + self.expect( + 'frame variable -d run-target *cfSetRef', + patterns=[ + '\(CFSetRef\) \*cfSetRef =', + '\[0\] = 0x.* @".*"', + '\[1\] = 0x.* @".*"', + ]) self.expect( 'frame variable iset1 iset2 imset', Index: lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp =================================================================== --- lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -610,6 +610,10 @@ lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSCFSet synthetic children", ConstString("__NSCFSet"), ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "CFSetRef synthetic children", ConstString("CFSetRef"), + ScriptedSyntheticChildren::Flags()); AddCXXSynthetic( objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, Index: lldb/source/Plugins/Language/ObjC/NSSet.cpp =================================================================== --- lldb/source/Plugins/Language/ObjC/NSSet.cpp +++ lldb/source/Plugins/Language/ObjC/NSSet.cpp @@ -282,6 +282,7 @@ static const ConstString g_OrderedSetI("__NSOrderedSetI"); static const ConstString g_SetM("__NSSetM"); static const ConstString g_SetCF("__NSCFSet"); + static const ConstString g_SetCFRef("CFSetRef"); if (class_name.IsEmpty()) return false; @@ -306,7 +307,7 @@ } if (error.Fail()) return false; - } else if (class_name == g_SetCF) { + } else if (class_name == g_SetCF || class_name == g_SetCFRef) { ExecutionContext exe_ctx(process_sp); CFBasicHash cfbh; if (!cfbh.Update(valobj_addr, exe_ctx)) @@ -367,6 +368,7 @@ static const ConstString g_OrderedSetI("__NSOrderedSetI"); static const ConstString g_SetM("__NSSetM"); static const ConstString g_SetCF("__NSCFSet"); + static const ConstString g_SetCFRef("CFSetRef"); if (class_name.IsEmpty()) return nullptr; @@ -386,7 +388,7 @@ } else { return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); } - } else if (class_name == g_SetCF) { + } else if (class_name == g_SetCF || class_name == g_SetCFRef) { return (new NSCFSetSyntheticFrontEnd(valobj_sp)); } else { auto &map(NSSet_Additionals::GetAdditionalSynthetics()); Index: lldb/source/Core/ValueObject.cpp =================================================================== --- lldb/source/Core/ValueObject.cpp +++ lldb/source/Core/ValueObject.cpp @@ -49,6 +49,8 @@ #include "lldb/Utility/StreamString.h" #include "lldb/lldb-private-types.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" + #include "llvm/Support/Compiler.h" #include <algorithm> @@ -660,6 +662,7 @@ uint32_t child_bitfield_bit_offset = 0; bool child_is_base_class = false; bool child_is_deref_of_parent = false; + CompilerType compiler_type = GetCompilerType(); uint64_t language_flags = 0; const bool transparent_pointers = !synthetic_array_member; @@ -667,7 +670,7 @@ ExecutionContext exe_ctx(GetExecutionContextRef()); - child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex( + child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex( &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, @@ -687,6 +690,11 @@ language_flags); } + if (!valobj && synthetic_array_member) + valobj = GetSyntheticValue() + ->GetChildAtIndex(synthetic_index, synthetic_array_member) + .get(); + return valobj; } @@ -2830,6 +2838,47 @@ child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid, language_flags); } + + // In case of C opaque pointers, create an empty struct type and try to + // recreate a new ValueObjectChild using it. + if (!m_deref_valobj) { + if (llvm::isa<TypeSystemClang>(compiler_type.GetTypeSystem())) { + if (HasSyntheticValue()) { + TargetSP target_sp = GetTargetSP(); + TypeSystemClang *target_ast_context = + TypeSystemClang::GetScratch(*target_sp.get()); + + if (target_ast_context) { + ConstString g___lldb_opaque_ptr_type( + compiler_type.GetTypeName().AsCString()); + + child_compiler_type = target_ast_context->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, + g___lldb_opaque_ptr_type.GetCString(), clang::TTK_Struct, + lldb::eLanguageTypeC); + + if (child_compiler_type) { + TypeSystemClang::StartTagDeclarationDefinition( + child_compiler_type); + TypeSystemClang::CompleteTagDeclarationDefinition( + child_compiler_type); + + ConstString child_name; + if (!child_name_str.empty()) + child_name.SetCString(child_name_str.c_str()); + + m_deref_valobj = new ValueObjectChild( + *this, child_compiler_type, child_name, child_byte_size, + child_byte_offset, child_bitfield_bit_size, + child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, eAddressTypeInvalid, + language_flags); + } + } + } + } + } + } else if (HasSyntheticValue()) { m_deref_valobj = GetSyntheticValue()
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits