diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp --- a/lldb/source/Core/ValueObject.cpp +++ b/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 @@ -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(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() diff --git a/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/lldb/source/Plugins/Language/ObjC/NSSet.cpp --- a/lldb/source/Plugins/Language/ObjC/NSSet.cpp +++ b/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()); diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp --- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/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, diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py +++ b/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', diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m --- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m +++ b/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);