From 9d5e95d094ffc1a49aa4c9d379cec7c2b60fd3f2 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 6 Aug 2021 17:24:47 -0700 Subject: [PATCH] Re-land "[lldb] Upstream support for Foundation constant classes" Upstream support for NSConstantArray, NSConstantIntegerNumber, NSConstant{Float,Double}Number and NSConstantDictionary. We would've upstreamed this earlier but testing it requires -fno-constant-nsnumber-literals, -fno-constant-nsarray-literals and -fno-constant-nsdictionary-literals which haven't been upstreamed yet. As a temporary workaround use the system compiler (xcrun clang) for the constant variant of the tests. I'm just upstreaming this. The patch and the tests were all authored by Fred Riss. Differential revision: https://reviews.llvm.org/D107660 --- lldb/source/Plugins/Language/ObjC/Cocoa.cpp | 102 ++++++++++- lldb/source/Plugins/Language/ObjC/NSArray.cpp | 26 +++ .../Plugins/Language/ObjC/NSDictionary.cpp | 168 +++++++++++++++++- .../Plugins/Language/ObjC/ObjCLanguage.cpp | 28 +++ .../ObjCDataFormatterTestCase.py | 15 +- .../TestDataFormatterObjCNSBundle.py | 7 +- .../TestDataFormatterObjCNSContainer.py | 2 +- .../TestDataFormatterObjCNSData.py | 7 +- .../TestDataFormatterObjCNSDate.py | 2 +- .../TestDataFormatterObjCNSError.py | 7 +- .../TestDataFormatterObjCNSNumber.py | 67 +++++++ .../TestDataFormatterObjCNSURL.py | 7 +- .../TestDataFormatterObjNSException.py | 7 +- .../data-formatter/data-formatter-objc/main.m | 8 + .../TestNSDictionarySynthetic.py | 17 ++ .../nssetsynth/TestNSSetSynthetic.py | 17 ++ .../poarray/TestPrintObjectArray.py | 14 ++ .../lang/objc/orderedset/TestOrderedSet.py | 16 ++ .../TestObjCSingleEntryDictionary.py | 18 ++ 19 files changed, 516 insertions(+), 19 deletions(-) create mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSNumber.py diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp index 1479f4f0c1510..27017789e5f2e 100644 --- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp @@ -7,7 +7,9 @@ //===----------------------------------------------------------------------===// #include "Cocoa.h" +#include "NSString.h" +#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/Mangled.h" #include "lldb/Core/ValueObject.h" @@ -28,9 +30,37 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/bit.h" -#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" - -#include "NSString.h" +// Objective-C Type Encoding +#define _C_ID '@' +#define _C_CLASS '#' +#define _C_SEL ':' +#define _C_CHR 'c' +#define _C_UCHR 'C' +#define _C_SHT 's' +#define _C_USHT 'S' +#define _C_INT 'i' +#define _C_UINT 'I' +#define _C_LNG 'l' +#define _C_ULNG 'L' +#define _C_LNG_LNG 'q' +#define _C_ULNG_LNG 'Q' +#define _C_FLT 'f' +#define _C_DBL 'd' +#define _C_BFLD 'b' +#define _C_BOOL 'B' +#define _C_VOID 'v' +#define _C_UNDEF '?' +#define _C_PTR '^' +#define _C_CHARPTR '*' +#define _C_ATOM '%' +#define _C_ARY_B '[' +#define _C_ARY_E ']' +#define _C_UNION_B '(' +#define _C_UNION_E ')' +#define _C_STRUCT_B '{' +#define _C_STRUCT_E '}' +#define _C_VECTOR '!' +#define _C_CONST 'r' using namespace lldb; using namespace lldb_private; @@ -456,6 +486,72 @@ bool lldb_private::formatters::NSNumberSummaryProvider( 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 index b0398dd19c021..f18b59fb11ffe 100644 --- a/lldb/source/Plugins/Language/ObjC/NSArray.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSArray.cpp @@ -280,6 +280,22 @@ namespace Foundation1436 { } } +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 @@ bool lldb_private::formatters::NSArraySummaryProvider( 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 @@ bool lldb_private::formatters::NSArraySummaryProvider( 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 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( 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 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( 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 index 326f47a106605..d8bf034e731b0 100644 --- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -142,6 +142,38 @@ class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd { 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 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( 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 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( 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 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( 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 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( 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 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( 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 @@ lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::GetChildAtIndex( 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 index 379c53432b7b1..613b2fb2d8a5a 100644 --- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -403,6 +403,9 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { 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 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { 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 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { 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 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { 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 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { 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 index c31af352037fc..db7f823493f15 100644 --- 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 @@ class ObjCDataFormatterTestCase(TestBase): 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 index 673366fcbb3e4..84fd49b07b86f 100644 --- 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 @@ class ObjCDataFormatterNSBundle(ObjCDataFormatterTestCase): 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 index 26ebf28929ff5..375aefe36422c 100644 --- 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 @@ class ObjCDataFormatterNSContainer(ObjCDataFormatterTestCase): 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 index f1c5554eebfb5..846e1d9bb69a9 100644 --- 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 @@ class ObjCDataFormatterNSData(ObjCDataFormatterTestCase): 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 index 622bb4a327ed3..06996b1c151bd 100644 --- 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 @@ class ObjCDataFormatterNSDate(ObjCDataFormatterTestCase): 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 index 92f1f46deba43..8a3773a590ea6 100644 --- 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 @@ class ObjCDataFormatterNSError(ObjCDataFormatterTestCase): 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 index 0000000000000..47e272d4fe2e1 --- /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 index b746c49072361..c16e0986b082a 100644 --- 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 @@ class ObjCDataFormatterNSURL(ObjCDataFormatterTestCase): 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 index cf4144458dde0..664425d05f058 100644 --- 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 @@ class ObjCDataFormatterNSException(ObjCDataFormatterTestCase): 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 index e1e6d1a1b759e..0ca5cf98bd3a5 100644 --- 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 @@ int main(int argc, const char *argv[]) { 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 index b77d01a8086c3..eb54f53bd8113 100644 --- 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 setUp(self): 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 index feac24be836d0..219ed2c3aacba 100644 --- 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 setUp(self): 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 index 626e6cd16e8f7..3fcb2794b9520 100644 --- a/lldb/test/API/functionalities/data-formatter/poarray/TestPrintObjectArray.py +++ b/lldb/test/API/functionalities/data-formatter/poarray/TestPrintObjectArray.py @@ -20,6 +20,20 @@ def test_print_array(self): 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 index 80cb97a9d108c..ac7af265b27c1 100644 --- a/lldb/test/API/lang/objc/orderedset/TestOrderedSet.py +++ b/lldb/test/API/lang/objc/orderedset/TestOrderedSet.py @@ -8,6 +8,22 @@ class TestOrderedSet(TestBase): 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 index d50cbb39246bc..88d2536a16181 100644 --- 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 @@ def setUp(self): # 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)