diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp --- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "Cocoa.h" +#include "objc/runtime.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/Mangled.h" @@ -456,6 +457,72 @@ if (class_name == "NSDecimalNumber") return NSDecimalNumberSummaryProvider(valobj, stream, options); + if (class_name == "NSConstantIntegerNumber") { + Status error; + int64_t value = process_sp->ReadSignedIntegerFromMemory( + valobj_addr + 2 * ptr_size, 8, 0, error); + if (error.Fail()) + return false; + uint64_t encoding_addr = process_sp->ReadUnsignedIntegerFromMemory( + valobj_addr + ptr_size, ptr_size, 0, error); + if (error.Fail()) + return false; + char encoding = + process_sp->ReadUnsignedIntegerFromMemory(encoding_addr, 1, 0, error); + if (error.Fail()) + return false; + + switch (encoding) { + case _C_CHR: + NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); + return true; + case _C_SHT: + NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage()); + return true; + case _C_INT: + NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage()); + return true; + case _C_LNG: + case _C_LNG_LNG: + NSNumber_FormatLong(valobj, stream, value, options.GetLanguage()); + return true; + + case _C_UCHR: + case _C_USHT: + case _C_UINT: + case _C_ULNG: + case _C_ULNG_LNG: + stream.Printf("%" PRIu64, value); + return true; + } + + return false; + } + + if (class_name == "NSConstantFloatNumber") { + Status error; + uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory( + valobj_addr + ptr_size, 4, 0, error); + if (error.Fail()) + return false; + float flt_value = 0.0f; + memcpy(&flt_value, &flt_as_int, sizeof(flt_as_int)); + NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage()); + return true; + } + + if (class_name == "NSConstantDoubleNumber") { + Status error; + uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory( + valobj_addr + ptr_size, 8, 0, error); + if (error.Fail()) + return false; + double dbl_value = 0.0; + memcpy(&dbl_value, &dbl_as_lng, sizeof(dbl_as_lng)); + NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage()); + return true; + } + if (class_name == "NSNumber" || class_name == "__NSCFNumber") { int64_t value = 0; uint64_t i_bits = 0; diff --git a/lldb/source/Plugins/Language/ObjC/NSArray.cpp b/lldb/source/Plugins/Language/ObjC/NSArray.cpp --- a/lldb/source/Plugins/Language/ObjC/NSArray.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSArray.cpp @@ -280,6 +280,22 @@ } } +namespace ConstantArray { + +struct ConstantArray32 { + uint64_t used; + uint32_t list; +}; + +struct ConstantArray64 { + uint64_t used; + uint64_t list; +}; + +using NSConstantArraySyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd; +} // namespace ConstantArray + class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); @@ -356,6 +372,7 @@ static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy"); static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable"); static const ConstString g_NSCallStackArray("_NSCallStackArray"); + static const ConstString g_NSConstantArray("NSConstantArray"); if (class_name.IsEmpty()) return false; @@ -366,6 +383,12 @@ ptr_size, 0, error); if (error.Fail()) return false; + } else if (class_name == g_NSConstantArray) { + Status error; + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 8, + 0, error); + if (error.Fail()) + return false; } else if (class_name == g_NSArrayM) { AppleObjCRuntime *apple_runtime = llvm::dyn_cast_or_null(runtime); @@ -803,6 +826,7 @@ ConstString class_name(descriptor->GetClassName()); static const ConstString g_NSArrayI("__NSArrayI"); + static const ConstString g_NSConstantArray("NSConstantArray"); static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer"); static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM"); static const ConstString g_NSArrayM("__NSArrayM"); @@ -823,6 +847,8 @@ return (new Foundation1300::NSArrayISyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArrayI_Transfer) { return (new Foundation1436::NSArrayI_TransferSyntheticFrontEnd(valobj_sp)); + } else if (class_name == g_NSConstantArray) { + return new ConstantArray::NSConstantArraySyntheticFrontEnd(valobj_sp); } else if (class_name == g_NSFrozenArrayM) { return (new Foundation1436::NSFrozenArrayMSyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArray0) { diff --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp --- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -142,6 +142,38 @@ std::vector m_children; }; +class NSConstantDictionarySyntheticFrontEnd : public SyntheticChildrenFrontEnd { +public: + NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + size_t CalculateNumChildren() override; + + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + + bool Update() override; + + bool MightHaveChildren() override; + + size_t GetIndexOfChildWithName(ConstString name) override; + +private: + ExecutionContextRef m_exe_ctx_ref; + CompilerType m_pair_type; + uint8_t m_ptr_size = 8; + lldb::ByteOrder m_order = lldb::eByteOrderInvalid; + unsigned int m_size = 0; + lldb::addr_t m_keys_ptr = LLDB_INVALID_ADDRESS; + lldb::addr_t m_objects_ptr = LLDB_INVALID_ADDRESS; + + struct DictionaryItemDescriptor { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + std::vector m_children; +}; + class NSCFDictionarySyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); @@ -416,6 +448,7 @@ static const ConstString g_DictionaryCF("__CFDictionary"); static const ConstString g_DictionaryNSCF("__NSCFDictionary"); static const ConstString g_DictionaryCFRef("CFDictionaryRef"); + static const ConstString g_ConstantDictionary("NSConstantDictionary"); if (class_name.IsEmpty()) return false; @@ -428,8 +461,14 @@ return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); - } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy - || class_name == g_DictionaryMFrozen) { + } else if (class_name == g_ConstantDictionary) { + Status error; + value = process_sp->ReadUnsignedIntegerFromMemory( + valobj_addr + 2 * ptr_size, ptr_size, 0, error); + if (error.Fail()) + return false; + } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy || + class_name == g_DictionaryMFrozen) { AppleObjCRuntime *apple_runtime = llvm::dyn_cast_or_null(runtime); Status error; @@ -447,8 +486,7 @@ value = 1; } else if (class_name == g_Dictionary0) { value = 0; - } else if (class_name == g_DictionaryCF || - class_name == g_DictionaryNSCF || + } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF || class_name == g_DictionaryCFRef) { ExecutionContext exe_ctx(process_sp); CFBasicHash cfbh; @@ -517,12 +555,15 @@ static const ConstString g_DictionaryCF("__CFDictionary"); static const ConstString g_DictionaryNSCF("__NSCFDictionary"); static const ConstString g_DictionaryCFRef("CFDictionaryRef"); + static const ConstString g_ConstantDictionary("NSConstantDictionary"); if (class_name.IsEmpty()) return nullptr; if (class_name == g_DictionaryI) { return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); + } else if (class_name == g_ConstantDictionary) { + return (new NSConstantDictionarySyntheticFrontEnd(valobj_sp)); } else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) { if (runtime->GetFoundationVersion() >= 1437) { return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp)); @@ -532,11 +573,10 @@ return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } } else if (class_name == g_DictionaryMLegacy) { - return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); + return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } else if (class_name == g_Dictionary1) { return (new NSDictionary1SyntheticFrontEnd(valobj_sp)); - } else if (class_name == g_DictionaryCF || - class_name == g_DictionaryNSCF || + } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF || class_name == g_DictionaryCFRef) { return (new NSCFDictionarySyntheticFrontEnd(valobj_sp)); } else { @@ -830,6 +870,120 @@ return dict_item.valobj_sp; } +lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd:: + NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp) {} + +size_t lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd:: + GetIndexOfChildWithName(ConstString name) { + const char *item_name = name.GetCString(); + uint32_t idx = ExtractIndexFromString(item_name); + if (idx < UINT32_MAX && idx >= CalculateNumChildren()) + return UINT32_MAX; + return idx; +} + +size_t lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd:: + CalculateNumChildren() { + return m_size; +} + +bool lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::Update() { + ValueObjectSP valobj_sp = m_backend.GetSP(); + if (!valobj_sp) + return false; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + Status error; + error.Clear(); + lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); + if (!process_sp) + return false; + m_ptr_size = process_sp->GetAddressByteSize(); + m_order = process_sp->GetByteOrder(); + uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0); + m_size = process_sp->ReadUnsignedIntegerFromMemory( + valobj_addr + 2 * m_ptr_size, m_ptr_size, 0, error); + if (error.Fail()) + return false; + m_keys_ptr = + process_sp->ReadPointerFromMemory(valobj_addr + 3 * m_ptr_size, error); + if (error.Fail()) + return false; + m_objects_ptr = + process_sp->ReadPointerFromMemory(valobj_addr + 4 * m_ptr_size, error); + return !error.Fail(); +} + +bool lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd:: + MightHaveChildren() { + return true; +} + +lldb::ValueObjectSP lldb_private::formatters:: + NSConstantDictionarySyntheticFrontEnd::GetChildAtIndex(size_t idx) { + uint32_t num_children = CalculateNumChildren(); + + if (idx >= num_children) + return lldb::ValueObjectSP(); + + if (m_children.empty()) { + // do the scan phase + lldb::addr_t key_at_idx = 0, val_at_idx = 0; + ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); + if (!process_sp) + return lldb::ValueObjectSP(); + + for (unsigned int child = 0; child < num_children; ++child) { + Status error; + key_at_idx = process_sp->ReadPointerFromMemory( + m_keys_ptr + child * m_ptr_size, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + val_at_idx = process_sp->ReadPointerFromMemory( + m_objects_ptr + child * m_ptr_size, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx, + lldb::ValueObjectSP()}; + m_children.push_back(descriptor); + } + } + + if (idx >= m_children.size()) // should never happen + return lldb::ValueObjectSP(); + + DictionaryItemDescriptor &dict_item = m_children[idx]; + if (!dict_item.valobj_sp) { + if (!m_pair_type.IsValid()) { + TargetSP target_sp(m_backend.GetTargetSP()); + if (!target_sp) + return ValueObjectSP(); + m_pair_type = GetLLDBNSPairType(target_sp); + } + if (!m_pair_type.IsValid()) + return ValueObjectSP(); + + DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0)); + + if (m_ptr_size == 8) { + uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); + *data_ptr = dict_item.key_ptr; + *(data_ptr + 1) = dict_item.val_ptr; + } else { + uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); + *data_ptr = dict_item.key_ptr; + *(data_ptr + 1) = dict_item.val_ptr; + } + + StreamString idx_name; + idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); + DataExtractor data(buffer_sp, m_order, m_ptr_size); + dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data, + m_exe_ctx_ref, m_pair_type); + } + return dict_item.valobj_sp; +} + lldb_private::formatters::NSDictionary1SyntheticFrontEnd:: NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp.get()), m_pair(nullptr) {} 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 @@ -403,6 +403,9 @@ AddCXXSummary( objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSArray"), appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", ConstString("NSConstantArray"), appkit_flags); AddCXXSummary( objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags); @@ -437,6 +440,10 @@ lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider, + "NSDictionary summary provider", + ConstString("NSConstantDictionary"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", @@ -543,6 +550,10 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSArray"), ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", ConstString("NSConstantArray"), + ScriptedSyntheticChildren::Flags()); AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSMutableArray"), @@ -570,6 +581,11 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryM"), ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", ConstString("NSConstantDictionary"), + ScriptedSyntheticChildren::Flags()); AddCXXSynthetic( objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, @@ -791,6 +807,18 @@ AddCXXSummary( objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSNumber"), appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", + ConstString("NSConstantIntegerNumber"), appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", + ConstString("NSConstantDoubleNumber"), appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", + ConstString("NSConstantFloatNumber"), appkit_flags); AddCXXSummary( objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags); diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/ObjCDataFormatterTestCase.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/ObjCDataFormatterTestCase.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/ObjCDataFormatterTestCase.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/ObjCDataFormatterTestCase.py @@ -14,8 +14,19 @@ mydir = TestBase.compute_mydir(__file__) - def appkit_tester_impl(self, commands): - self.build() + def appkit_tester_impl(self, commands, use_constant_classes): + if use_constant_classes: + self.build() + else: + disable_constant_classes = { + 'CC': + 'xcrun clang', # FIXME: Remove when flags are available upstream. + 'CFLAGS_EXTRAS': + '-fno-constant-nsnumber-literals ' + + '-fno-constant-nsarray-literals ' + + '-fno-constant-nsdictionary-literals' + } + self.build(dictionary=disable_constant_classes) self.appkit_common_data_formatters_command() commands() diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSBundle.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSBundle.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSBundle.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSBundle.py @@ -16,7 +16,12 @@ def test_nsbundle_with_run_command(self): """Test formatters for NSBundle.""" - self.appkit_tester_impl(self.nsbundle_data_formatter_commands) + self.appkit_tester_impl(self.nsbundle_data_formatter_commands, True) + + @skipUnlessDarwin + def test_nsbundle_with_run_command_no_sonct(self): + """Test formatters for NSBundle.""" + self.appkit_tester_impl(self.nsbundle_data_formatter_commands, False) def nsbundle_data_formatter_commands(self): self.expect( 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 @@ -16,7 +16,7 @@ def test_nscontainers_with_run_command(self): """Test formatters for NS container classes.""" - self.appkit_tester_impl(self.nscontainers_data_formatter_commands) + self.appkit_tester_impl(self.nscontainers_data_formatter_commands, False) def nscontainers_data_formatter_commands(self): self.expect( diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSData.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSData.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSData.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSData.py @@ -16,7 +16,12 @@ def test_nsdata_with_run_command(self): """Test formatters for NSData.""" - self.appkit_tester_impl(self.nsdata_data_formatter_commands) + self.appkit_tester_impl(self.nsdata_data_formatter_commands, True) + + @skipUnlessDarwin + def test_nsdata_with_run_command_no_const(self): + """Test formatters for NSData.""" + self.appkit_tester_impl(self.nsdata_data_formatter_commands, False) def nsdata_data_formatter_commands(self): self.expect( diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py @@ -17,7 +17,7 @@ def test_nsdate_with_run_command(self): """Test formatters for NSDate.""" - self.appkit_tester_impl(self.nsdate_data_formatter_commands) + self.appkit_tester_impl(self.nsdate_data_formatter_commands, False) def nsdate_data_formatter_commands(self): self.expect( diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSError.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSError.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSError.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSError.py @@ -16,7 +16,12 @@ def test_nserror_with_run_command(self): """Test formatters for NSError.""" - self.appkit_tester_impl(self.nserror_data_formatter_commands) + self.appkit_tester_impl(self.nserror_data_formatter_commands, True) + + @skipUnlessDarwin + def test_nserror_with_run_command_no_const(self): + """Test formatters for NSError.""" + self.appkit_tester_impl(self.nserror_data_formatter_commands, False) def nserror_data_formatter_commands(self): self.expect( diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSNumber.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSNumber.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSNumber.py @@ -0,0 +1,67 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterNSNumber(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_nsnumber_with_run_command(self): + """Test formatters for NS container classes.""" + self.appkit_tester_impl(self.nscontainers_data_formatter_commands, True) + + @skipUnlessDarwin + def test_nsnumber_with_run_command_no_const(self): + """Test formatters for NS container classes.""" + self.appkit_tester_impl(self.nscontainers_data_formatter_commands, False) + + def nscontainers_data_formatter_commands(self): + self.expect( + 'frame variable newArray nsDictionary newDictionary nscfDictionary cfDictionaryRef newMutableDictionary cfarray_ref mutable_array_ref', + substrs=[ + '(NSArray *) newArray = ', '@"50 elements"', + '(NSDictionary *) nsDictionary = ', ' 2 key/value pairs', + '(NSDictionary *) newDictionary = ', ' 12 key/value pairs', + '(CFDictionaryRef) cfDictionaryRef = ', ' 2 key/value pairs', + '(NSDictionary *) newMutableDictionary = ', ' 21 key/value pairs', + '(CFArrayRef) cfarray_ref = ', '@"3 elements"', + '(CFMutableArrayRef) mutable_array_ref = ', '@"11 elements"' + ]) + + numbers = [ ("num1", "(int)5"), + ("num2", "(float)3.140000"), + ("num3", "(double)3.14"), + ("num4", "(int128_t)18446744073709551614"), + ("num5", "(char)65"), + ("num6", "(long)255"), + ("num7", "(long)2000000"), + ("num8_Y", "YES"), + ("num8_N", "NO"), + ("num9", "(short)-31616"), + ("num_at1", "(int)12"), + ("num_at2", "(int)-12"), + ("num_at3", "(double)12.5"), + ("num_at4", "(double)-12.5"), + ("num_at5", "(char)97"), + ("num_at6", "(float)42.123"), + ("num_at7", "(double)43.123"), + ("num_at8", "(long)12345"), + ("num_at9", "17375808098308635870"), + ("num_at9b", "-1070935975400915746"), + ("num_at10", "YES"), + ("num_at11", "NO"), + ] + + for var, res in numbers: + self.expect('frame variable ' + var, substrs=[res]) + diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSURL.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSURL.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSURL.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSURL.py @@ -16,7 +16,12 @@ def test_nsurl_with_run_command(self): """Test formatters for NSURL.""" - self.appkit_tester_impl(self.nsurl_data_formatter_commands) + self.appkit_tester_impl(self.nsurl_data_formatter_commands, True) + + @skipUnlessDarwin + def test_nsurl_with_run_command_no_const(self): + """Test formatters for NSURL.""" + self.appkit_tester_impl(self.nsurl_data_formatter_commands, False) def nsurl_data_formatter_commands(self): self.expect( diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjNSException.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjNSException.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjNSException.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjNSException.py @@ -16,7 +16,12 @@ def test_nsexception_with_run_command(self): """Test formatters for NSException.""" - self.appkit_tester_impl(self.nsexception_data_formatter_commands) + self.appkit_tester_impl(self.nsexception_data_formatter_commands, True) + + @skipUnlessDarwin + def test_nsexception_with_run_command_no_const(self): + """Test formatters for NSException.""" + self.appkit_tester_impl(self.nsexception_data_formatter_commands, False) def nsexception_data_formatter_commands(self): self.expect( 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 @@ -154,6 +154,14 @@ NSNumber *num_at2 = @-12; NSNumber *num_at3 = @12.5; NSNumber *num_at4 = @-12.5; + NSNumber *num_at5 = @'a'; + NSNumber *num_at6 = @42.123f; + NSNumber *num_at7 = @43.123; + NSNumber *num_at8 = @12345ll; + NSNumber *num_at9 = @0xF1234567890abcdeull; + NSNumber *num_at9b = @-1070935975400915746; + NSNumber *num_at10 = @YES; + NSNumber *num_at11 = @NO; NSDecimalNumber *decimal_number = [NSDecimalNumber decimalNumberWithMantissa:123456 diff --git a/lldb/test/API/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py b/lldb/test/API/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py --- a/lldb/test/API/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py +++ b/lldb/test/API/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py @@ -24,6 +24,23 @@ def test_rdar11988289_with_run_command(self): """Test that NSDictionary reports its synthetic children properly.""" self.build() + self.run_tests() + + @skipUnlessDarwin + def test_rdar11988289_with_run_command_no_const(self): + """Test that NSDictionary reports its synthetic children properly.""" + disable_constant_classes = { + 'CC': + 'xcrun clang', # FIXME: Remove when flags are available upstream. + 'CFLAGS_EXTRAS': + '-fno-constant-nsnumber-literals ' + + '-fno-constant-nsarray-literals ' + + '-fno-constant-nsdictionary-literals' + } + self.build(dictionary=disable_constant_classes) + self.run_tests() + + def run_tests(self): self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) lldbutil.run_break_set_by_file_and_line( diff --git a/lldb/test/API/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py b/lldb/test/API/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py --- a/lldb/test/API/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py +++ b/lldb/test/API/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py @@ -24,6 +24,23 @@ def test_rdar12529957_with_run_command(self): """Test that NSSet reports its synthetic children properly.""" self.build() + self.run_tests() + + @skipUnlessDarwin + def test_rdar12529957_with_run_command_no_const(self): + """Test that NSSet reports its synthetic children properly.""" + disable_constant_classes = { + 'CC': + 'xcrun clang', # FIXME: Remove when flags are available upstream. + 'CFLAGS_EXTRAS': + '-fno-constant-nsnumber-literals ' + + '-fno-constant-nsarray-literals ' + + '-fno-constant-nsdictionary-literals' + } + self.build(dictionary=disable_constant_classes) + self.run_tests() + + def run_tests(self): self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) lldbutil.run_break_set_by_file_and_line( diff --git a/lldb/test/API/functionalities/data-formatter/poarray/TestPrintObjectArray.py b/lldb/test/API/functionalities/data-formatter/poarray/TestPrintObjectArray.py --- a/lldb/test/API/functionalities/data-formatter/poarray/TestPrintObjectArray.py +++ b/lldb/test/API/functionalities/data-formatter/poarray/TestPrintObjectArray.py @@ -20,6 +20,20 @@ self.build() self.printarray_data_formatter_commands() + @skipUnlessDarwin + def test_print_array_no_const(self): + """Test that expr -O -Z works""" + disable_constant_classes = { + 'CC': + 'xcrun clang', # FIXME: Remove when flags are available upstream. + 'CFLAGS_EXTRAS': + '-fno-constant-nsnumber-literals ' + + '-fno-constant-nsarray-literals ' + + '-fno-constant-nsdictionary-literals' + } + self.build(dictionary=disable_constant_classes) + self.printarray_data_formatter_commands() + def setUp(self): # Call super's setUp(). TestBase.setUp(self) diff --git a/lldb/test/API/lang/objc/orderedset/TestOrderedSet.py b/lldb/test/API/lang/objc/orderedset/TestOrderedSet.py --- a/lldb/test/API/lang/objc/orderedset/TestOrderedSet.py +++ b/lldb/test/API/lang/objc/orderedset/TestOrderedSet.py @@ -8,6 +8,22 @@ def test_ordered_set(self): self.build() + self.run_tests() + + @skipUnlessDarwin + def test_ordered_set_no_const(self): + disable_constant_classes = { + 'CC': + 'xcrun clang', # FIXME: Remove when flags are available upstream. + 'CFLAGS_EXTRAS': + '-fno-constant-nsnumber-literals ' + + '-fno-constant-nsarray-literals ' + + '-fno-constant-nsdictionary-literals' + } + self.build(dictionary=disable_constant_classes) + self.run_tests() + + def run_tests(self): src_file = "main.m" src_file_spec = lldb.SBFileSpec(src_file) (target, process, thread, main_breakpoint) = lldbutil.run_to_source_breakpoint(self, diff --git a/lldb/test/API/lang/objc/single-entry-dictionary/TestObjCSingleEntryDictionary.py b/lldb/test/API/lang/objc/single-entry-dictionary/TestObjCSingleEntryDictionary.py --- a/lldb/test/API/lang/objc/single-entry-dictionary/TestObjCSingleEntryDictionary.py +++ b/lldb/test/API/lang/objc/single-entry-dictionary/TestObjCSingleEntryDictionary.py @@ -21,9 +21,27 @@ # Find the line number to break inside main(). self.line = line_number('main.m', '// break here') + @skipUnlessDarwin @expectedFailureAll(oslist=['watchos'], bugnumber="rdar://problem/34642736") # bug in NSDictionary formatting on watchos def test_single_entry_dict(self): self.build() + self.run_tests() + + @skipUnlessDarwin + @expectedFailureAll(oslist=['watchos'], bugnumber="rdar://problem/34642736") # bug in NSDictionary formatting on watchos + def test_single_entry_dict_no_const(self): + disable_constant_classes = { + 'CC': + 'xcrun clang', # FIXME: Remove when flags are available upstream. + 'CFLAGS_EXTRAS': + '-fno-constant-nsnumber-literals ' + + '-fno-constant-nsarray-literals ' + + '-fno-constant-nsdictionary-literals' + } + self.build(dictionary=disable_constant_classes) + self.run_tests() + + def run_tests(self): exe = self.getBuildArtifact("a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)