forked from OSchip/llvm-project
Removing cascading through inheritance chains for data formatters
This is the feature that allowed the user to have things like: class Base { ... }; class Derived : public Base { ... }; and have formatters defined for Base work automatically for Derived. This feature turned out to be too expensive since it requires completing types. This patch takes care of removing cascading (other than typedefs chain cascading), updating the test suite accordingly, and adding required Cocoa class names to keep the AppKit formatters working llvm-svn: 153272
This commit is contained in:
parent
bdf975ea3f
commit
4a3274af96
|
@ -458,132 +458,6 @@ protected:
|
|||
return false;
|
||||
}
|
||||
|
||||
#define LLDB_MAX_REASONABLE_OBJC_CLASS_DEPTH 100
|
||||
|
||||
bool Get_ObjC(const lldb::ProcessSP &process_sp,
|
||||
ObjCLanguageRuntime::ObjCISA isa,
|
||||
std::set<ObjCLanguageRuntime::ObjCISA> &found_values,
|
||||
MapValueType& entry,
|
||||
uint32_t& reason)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
if (log)
|
||||
log->Printf("going to an Objective-C dynamic scanning");
|
||||
if (!process_sp)
|
||||
return false;
|
||||
ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
|
||||
if (runtime == NULL)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("no valid ObjC runtime, bailing out");
|
||||
return false;
|
||||
}
|
||||
if (runtime->IsValidISA(isa) == false)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("invalid ISA, bailing out");
|
||||
return false;
|
||||
}
|
||||
|
||||
ConstString name = runtime->GetActualTypeName(isa);
|
||||
if (log)
|
||||
log->Printf("looking for formatter for %s", name.GetCString());
|
||||
if (Get(name, entry))
|
||||
{
|
||||
if (log)
|
||||
log->Printf("direct match found, returning");
|
||||
return true;
|
||||
}
|
||||
if (log)
|
||||
log->Printf("no direct match");
|
||||
ObjCLanguageRuntime::ObjCISA parent = runtime->GetParentClass(isa);
|
||||
if (runtime->IsValidISA(parent) == false)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("invalid parent ISA, bailing out");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Put the isa value in our map. Then check the new_value, if it was already there, we've got a
|
||||
// loop in the inheritance hierarchy, and should bag out.
|
||||
std::pair<std::set<ObjCLanguageRuntime::ObjCISA>::iterator, bool> new_value = found_values.insert (isa);
|
||||
if (new_value.second == false)
|
||||
{
|
||||
//Our value already existed in the map.
|
||||
if (log)
|
||||
log->Printf ("ISA: 0x%llx already found in inheritance chain.", isa);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (found_values.size() > LLDB_MAX_REASONABLE_OBJC_CLASS_DEPTH)
|
||||
{
|
||||
// ObjC hierarchies are usually pretty shallow, if we've gone this far, we are probably chasing
|
||||
// uninitialized memory.
|
||||
if (log)
|
||||
log->Printf("Parent-child depth of %d, we are probably off in the weeds, bailing out.",
|
||||
LLDB_MAX_REASONABLE_OBJC_CLASS_DEPTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Get_ObjC(process_sp, parent, found_values, entry, reason))
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionNavigatedBaseClasses;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Get_CXXClass (ValueObject& valobj,
|
||||
const clang::Type* typePtr,
|
||||
MapValueType& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t& reason)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
if (log)
|
||||
log->Printf("working with C++");
|
||||
clang::CXXRecordDecl* record = typePtr->getAsCXXRecordDecl();
|
||||
if (record)
|
||||
{
|
||||
if (!record->hasDefinition())
|
||||
ClangASTContext::GetCompleteType(valobj.GetClangAST(), valobj.GetClangType());
|
||||
if (record->hasDefinition())
|
||||
{
|
||||
clang::CXXRecordDecl::base_class_iterator pos,end;
|
||||
if (record->getNumBases() > 0)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("look into bases");
|
||||
end = record->bases_end();
|
||||
for (pos = record->bases_begin(); pos != end; pos++)
|
||||
{
|
||||
if ((Get(valobj, pos->getType(), entry, use_dynamic, reason)) && entry->Cascades())
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionNavigatedBaseClasses;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (record->getNumVBases() > 0)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("look into VBases");
|
||||
end = record->vbases_end();
|
||||
for (pos = record->vbases_begin(); pos != end; pos++)
|
||||
{
|
||||
if ((Get(valobj, pos->getType(), entry, use_dynamic, reason)) && entry->Cascades())
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionNavigatedBaseClasses;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Get_BitfieldMatch (ValueObject& valobj,
|
||||
ConstString typeName,
|
||||
|
@ -612,68 +486,36 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Get_ObjCDynamic(lldb::ProcessSP process_sp,
|
||||
ValueObject& valobj,
|
||||
MapValueType& entry,
|
||||
uint32_t& reason)
|
||||
bool Get_ObjC (ValueObject& valobj,
|
||||
MapValueType& entry)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
if (!process_sp)
|
||||
return false;
|
||||
if (log)
|
||||
log->Printf("this is an ObjC 'id', let's do dynamic search");
|
||||
lldb::ProcessSP process_sp = valobj.GetProcessSP();
|
||||
ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
|
||||
if (runtime == NULL)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("no valid ObjC runtime, skipping dynamic");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
ObjCLanguageRuntime::ObjCISA isa = runtime->GetISA(valobj);
|
||||
if (runtime->IsValidISA(isa) == false)
|
||||
{
|
||||
std::set<ObjCLanguageRuntime::ObjCISA> found_values;
|
||||
if (Get_ObjC(process_sp, runtime->GetISA(valobj), found_values, entry, reason))
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionDynamicObjCHierarchy;
|
||||
return true;
|
||||
}
|
||||
if (log)
|
||||
log->Printf("invalid ISA, skipping dynamic");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Get_ObjCStatic(const clang::ObjCObjectType *objc_class_type,
|
||||
ValueObject& valobj,
|
||||
clang::QualType type,
|
||||
MapValueType& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t& reason)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
ConstString name = runtime->GetActualTypeName(isa);
|
||||
if (log)
|
||||
log->Printf("working with ObjC");
|
||||
clang::ASTContext *ast = valobj.GetClangAST();
|
||||
if (ClangASTContext::GetCompleteType(ast, valobj.GetClangType()) && !objc_class_type->isObjCId())
|
||||
log->Printf("dynamic type inferred is %s - looking for direct dynamic match", name.GetCString());
|
||||
if (Get(name, entry))
|
||||
{
|
||||
clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
|
||||
if (class_interface_decl)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("got an ObjCInterfaceDecl");
|
||||
clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
|
||||
if (superclass_interface_decl)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("got a parent class for this ObjC class");
|
||||
clang::QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl));
|
||||
if (Get(valobj, ivar_qual_type, entry, use_dynamic, reason) && entry->Cascades())
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionNavigatedBaseClasses;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (log)
|
||||
log->Printf("direct dynamic match found, returning");
|
||||
return true;
|
||||
}
|
||||
if (log)
|
||||
log->Printf("no dynamic match");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -690,7 +532,7 @@ protected:
|
|||
log->Printf("type is NULL, returning");
|
||||
return false;
|
||||
}
|
||||
// clang::QualType type = q_type.getUnqualifiedType();
|
||||
|
||||
type.removeLocalConst(); type.removeLocalVolatile(); type.removeLocalRestrict();
|
||||
const clang::Type* typePtr = type.getTypePtrOrNull();
|
||||
if (!typePtr)
|
||||
|
@ -721,7 +563,8 @@ protected:
|
|||
}
|
||||
if (log)
|
||||
log->Printf("no direct match");
|
||||
// look for a "base type", whatever that means
|
||||
|
||||
// strip pointers and references and see if that helps
|
||||
if (typePtr->isReferenceType())
|
||||
{
|
||||
if (log)
|
||||
|
@ -733,23 +576,6 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
lldb::ProcessSP process_sp = valobj.GetProcessSP();
|
||||
|
||||
if (use_dynamic != lldb::eNoDynamicValues &&
|
||||
ClangASTType::GetMinimumLanguage(valobj.GetClangAST(), valobj.GetClangType()) == lldb::eLanguageTypeObjC)
|
||||
{
|
||||
if (Get_ObjCDynamic(process_sp, valobj, entry, reason))
|
||||
return true;
|
||||
}
|
||||
else if (use_dynamic != lldb::eNoDynamicValues && log)
|
||||
{
|
||||
log->Printf("typename: %s, typePtr = %p, id = %p",
|
||||
typeName.AsCString(), typePtr, valobj.GetClangAST()->ObjCBuiltinIdTy.getTypePtr());
|
||||
}
|
||||
else if (log)
|
||||
{
|
||||
log->Printf("no dynamic");
|
||||
}
|
||||
if (typePtr->isPointerType())
|
||||
{
|
||||
if (log)
|
||||
|
@ -761,49 +587,29 @@ protected:
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (typePtr->isObjCObjectPointerType())
|
||||
{
|
||||
if (use_dynamic != lldb::eNoDynamicValues &&
|
||||
typeName == m_id_cs)
|
||||
if (use_dynamic != lldb::eNoDynamicValues)
|
||||
{
|
||||
if (Get_ObjCDynamic(process_sp, valobj, entry, reason))
|
||||
if (log)
|
||||
log->Printf("allowed to figure out dynamic ObjC type");
|
||||
if (Get_ObjC(valobj,entry))
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (log)
|
||||
log->Printf("stripping ObjC pointer");
|
||||
|
||||
// For some reason, C++ can quite easily obtain the type hierarchy for a ValueObject
|
||||
// even if the VO represent a pointer-to-class, as long as the typePtr is right
|
||||
// Objective-C on the other hand cannot really complete an @interface when
|
||||
// the VO refers to a pointer-to-@interface
|
||||
|
||||
Error error;
|
||||
ValueObject* target = valobj.Dereference(error).get();
|
||||
if (error.Fail() || !target)
|
||||
return false;
|
||||
if (Get(*target, typePtr->getPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers())
|
||||
log->Printf("dynamic disabled or failed - stripping ObjC pointer");
|
||||
clang::QualType pointee = typePtr->getPointeeType();
|
||||
if (Get(valobj, pointee, entry, use_dynamic, reason) && !entry->SkipsPointers())
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const clang::ObjCObjectType *objc_class_type = typePtr->getAs<clang::ObjCObjectType>();
|
||||
if (objc_class_type)
|
||||
{
|
||||
if (Get_ObjCStatic(objc_class_type,
|
||||
valobj,
|
||||
type,
|
||||
entry,
|
||||
use_dynamic,
|
||||
reason))
|
||||
return true;
|
||||
}
|
||||
// for C++ classes, navigate up the hierarchy
|
||||
if (typePtr->isRecordType())
|
||||
{
|
||||
if (Get_CXXClass(valobj, typePtr, entry, use_dynamic, reason))
|
||||
return true;
|
||||
}
|
||||
|
||||
// try to strip typedef chains
|
||||
const clang::TypedefType* type_tdef = type->getAs<clang::TypedefType>();
|
||||
if (type_tdef)
|
||||
|
|
|
@ -231,11 +231,10 @@ typedef enum FormatterChoiceCriterion
|
|||
eFormatterChoiceCriterionDirectChoice = 0x00000000,
|
||||
eFormatterChoiceCriterionStrippedPointerReference = 0x00000001,
|
||||
eFormatterChoiceCriterionNavigatedTypedefs = 0x00000002,
|
||||
eFormatterChoiceCriterionNavigatedBaseClasses = 0x00000004,
|
||||
eFormatterChoiceCriterionRegularExpressionSummary = 0x00000008,
|
||||
eFormatterChoiceCriterionRegularExpressionFilter = 0x00000008,
|
||||
eFormatterChoiceCriterionDynamicObjCHierarchy = 0x00000010,
|
||||
eFormatterChoiceCriterionStrippedBitField = 0x00000020
|
||||
eFormatterChoiceCriterionRegularExpressionSummary = 0x00000004,
|
||||
eFormatterChoiceCriterionRegularExpressionFilter = 0x00000004,
|
||||
eFormatterChoiceCriterionDynamicObjCDiscovery = 0x00000008,
|
||||
eFormatterChoiceCriterionStrippedBitField = 0x00000010
|
||||
} FormatterChoiceCriterion;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -527,7 +527,7 @@ public:
|
|||
OptionDefinition
|
||||
CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."},
|
||||
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
|
||||
{ LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
|
||||
{ LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
|
||||
};
|
||||
|
@ -1370,7 +1370,7 @@ OptionDefinition
|
|||
CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
|
||||
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."},
|
||||
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
|
||||
{ LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type."},
|
||||
{ LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
|
||||
{ LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
|
||||
|
@ -3558,7 +3558,7 @@ CommandObjectTypeSynthAdd::Execute (Args& command, CommandReturnObject &result)
|
|||
OptionDefinition
|
||||
CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."},
|
||||
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
|
||||
{ LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
|
||||
{ LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
|
||||
{ LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
|
||||
|
@ -3846,7 +3846,7 @@ public:
|
|||
OptionDefinition
|
||||
CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."},
|
||||
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
|
||||
{ LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
|
||||
{ LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
|
||||
{ LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
|
||||
|
|
|
@ -881,50 +881,77 @@ FormatManager::LoadObjCFormatters()
|
|||
.SetHideItemNames(false);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "CFArray.CFArray_SummaryProvider", ConstString("NSArray"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFArray.CFArray_SummaryProvider", ConstString("__NSArrayI"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFArray.CFArray_SummaryProvider", ConstString("__NSArrayM"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFArray.CFArray_SummaryProvider", ConstString("__NSCFArray"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFArray.CFArray_SummaryProvider", ConstString("CFArrayRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFArray.CFArray_SummaryProvider", ConstString("CFMutableArrayRef"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "CFBag.CFBag_SummaryProvider", ConstString("CFBagRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFBag.CFBag_SummaryProvider", ConstString("__CFBag"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFBag.CFBag_SummaryProvider", ConstString("const struct __CFBag"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFBag.CFBag_SummaryProvider", ConstString("CFMutableBagRef"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "CFBinaryHeap.CFBinaryHeap_SummaryProvider", ConstString("CFBinaryHeapRef"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "CFBinaryHeap.CFBinaryHeap_SummaryProvider", ConstString("__CFBinaryHeap"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "CFDictionary.CFDictionary_SummaryProvider", ConstString("NSDictionary"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFDictionary.CFDictionary_SummaryProvider2", ConstString("CFDictionaryRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFDictionary.CFDictionary_SummaryProvider2", ConstString("CFMutableDictionaryRef"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "CFDictionary.CFDictionary_SummaryProvider", ConstString("__NSCFDictionary"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFDictionary.CFDictionary_SummaryProvider", ConstString("__NSDictionaryI"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFDictionary.CFDictionary_SummaryProvider", ConstString("__NSDictionaryM"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "CFString.CFString_SummaryProvider", ConstString("NSString"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFString.CFString_SummaryProvider", ConstString("CFStringRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFString.CFString_SummaryProvider", ConstString("CFMutableStringRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFString.CFAttributedString_SummaryProvider", ConstString("NSAttributedString"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "CFString.CFString_SummaryProvider", ConstString("__NSCFConstantString"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFString.CFString_SummaryProvider", ConstString("__NSCFString"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFString.CFString_SummaryProvider", ConstString("NSCFConstantString"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFString.CFString_SummaryProvider", ConstString("NSCFString"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSBundle.NSBundle_SummaryProvider", ConstString("NSBundle"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSData.NSData_SummaryProvider", ConstString("NSData"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSData.NSData_SummaryProvider2", ConstString("CFDataRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSData.NSData_SummaryProvider2", ConstString("CFMutableDataRef"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSData.NSData_SummaryProvider", ConstString("NSConcreteData"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSData.NSData_SummaryProvider", ConstString("NSConcreteMutableData"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSData.NSData_SummaryProvider", ConstString("__NSCFData"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSException.NSException_SummaryProvider", ConstString("NSException"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSMachPort.NSMachPort_SummaryProvider", ConstString("NSMachPort"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSNotification.NSNotification_SummaryProvider", ConstString("NSNotification"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSNotification.NSNotification_SummaryProvider", ConstString("NSConcreteNotification"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSNumber.NSNumber_SummaryProvider", ConstString("NSNumber"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSNumber.NSNumber_SummaryProvider", ConstString("__NSCFBoolean"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSNumber.NSNumber_SummaryProvider", ConstString("__NSCFNumber"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSNumber.NSNumber_SummaryProvider", ConstString("NSCFBoolean"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSNumber.NSNumber_SummaryProvider", ConstString("NSCFNumber"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSSet.NSSet_SummaryProvider", ConstString("NSSet"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSSet.NSSet_SummaryProvider2", ConstString("CFSetRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSSet.NSSet_SummaryProvider2", ConstString("CFMutableSetRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSSet.NSSet_SummaryProvider", ConstString("__NSCFSet"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSSet.NSSet_SummaryProvider", ConstString("__NSSetI"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSSet.NSSet_SummaryProvider", ConstString("__NSSetM"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSSet.NSSet_SummaryProvider", ConstString("NSCountedSet"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSURL.NSURL_SummaryProvider", ConstString("NSURL"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSURL.NSURL_SummaryProvider", ConstString("CFURLRef"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSDate.NSDate_SummaryProvider", ConstString("NSDate"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSDate.NSDate_SummaryProvider", ConstString("__NSDate"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSDate.NSDate_SummaryProvider", ConstString("__NSTaggedDate"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSDate.NSDate_SummaryProvider", ConstString("NSCalendarDate"), appkit_flags);
|
||||
|
||||
AddScriptSummary(appkit_category_sp, "NSDate.NSTimeZone_SummaryProvider", ConstString("NSTimeZone"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSDate.NSTimeZone_SummaryProvider", ConstString("CFTimeZoneRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "NSDate.NSTimeZone_SummaryProvider", ConstString("__NSTimeZone"), appkit_flags);
|
||||
|
||||
// CFAbsoluteTime is actually a double rather than a pointer to an object
|
||||
// we do not care about the numeric value, since it is probably meaningless to users
|
||||
|
@ -939,6 +966,8 @@ FormatManager::LoadObjCFormatters()
|
|||
|
||||
AddScriptSummary(appkit_category_sp, "CFBitVector.CFBitVector_SummaryProvider", ConstString("CFBitVectorRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFBitVector.CFBitVector_SummaryProvider", ConstString("CFMutableBitVectorRef"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFBitVector.CFBitVector_SummaryProvider", ConstString("__CFBitVector"), appkit_flags);
|
||||
AddScriptSummary(appkit_category_sp, "CFBitVector.CFBitVector_SummaryProvider", ConstString("__CFMutableBitVector"), appkit_flags);
|
||||
|
||||
TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name);
|
||||
|
||||
|
|
|
@ -255,36 +255,35 @@ class CategoriesDataFormatterTestCase(TestBase):
|
|||
self.runCmd("type summary add Shape -w BaseCategory --summary-string \"AShape\"")
|
||||
self.runCmd("type category enable BaseCategory")
|
||||
|
||||
self.expect("frame variable c1 r1 c_ptr r_ptr",
|
||||
substrs = ['AShape',
|
||||
'AShape',
|
||||
'AShape',
|
||||
'AShape'])
|
||||
|
||||
self.expect("print (Shape*)&c1",
|
||||
substrs = ['AShape'])
|
||||
self.expect("print (Shape*)&r1",
|
||||
substrs = ['AShape'])
|
||||
self.expect("print (Shape*)c_ptr",
|
||||
substrs = ['AShape'])
|
||||
self.expect("print (Shape*)r_ptr",
|
||||
substrs = ['AShape'])
|
||||
|
||||
self.runCmd("type summary add Circle -w CircleCategory --summary-string \"ACircle\"")
|
||||
self.runCmd("type summary add Rectangle -w RectangleCategory --summary-string \"ARectangle\"")
|
||||
self.runCmd("type category enable CircleCategory")
|
||||
|
||||
self.expect("frame variable c1 r1 c_ptr r_ptr",
|
||||
substrs = ['ACircle',
|
||||
'AShape',
|
||||
'ACircle',
|
||||
'AShape'])
|
||||
self.expect("frame variable c1",
|
||||
substrs = ['ACircle'])
|
||||
self.expect("frame variable c_ptr",
|
||||
substrs = ['ACircle'])
|
||||
|
||||
self.runCmd("type summary add \"Rectangle *\" -w RectangleStarCategory --summary-string \"ARectangleStar\"")
|
||||
self.runCmd("type category enable RectangleStarCategory")
|
||||
|
||||
self.expect("frame variable c1 r1 c_ptr r_ptr",
|
||||
substrs = ['ACircle',
|
||||
'AShape',
|
||||
'ACircle',
|
||||
'ARectangleStar'])
|
||||
|
||||
self.runCmd("type category enable RectangleCategory")
|
||||
|
||||
self.expect("frame variable c1 r1 c_ptr r_ptr",
|
||||
substrs = ['ACircle',
|
||||
'ARectangle',
|
||||
'ACircle',
|
||||
'ARectangle'])
|
||||
|
||||
|
@ -293,14 +292,13 @@ class CategoriesDataFormatterTestCase(TestBase):
|
|||
|
||||
self.expect("frame variable c1 r1 c_ptr r_ptr",
|
||||
substrs = ['ACircle',
|
||||
'AShape',
|
||||
'(Rectangle) r1 = {', 'w = 5', 'h = 6',
|
||||
'ACircle',
|
||||
'ARectangleStar'])
|
||||
|
||||
# check that list commands work
|
||||
self.expect("type category list",
|
||||
substrs = ['RectangleStarCategory',
|
||||
'is enabled'])
|
||||
substrs = ['RectangleStarCategory is enabled'])
|
||||
|
||||
self.expect("type summary list",
|
||||
substrs = ['ARectangleStar'])
|
||||
|
@ -310,13 +308,10 @@ class CategoriesDataFormatterTestCase(TestBase):
|
|||
|
||||
# check that list commands work
|
||||
self.expect("type category list",
|
||||
substrs = ['CircleCategory',
|
||||
'not enabled'])
|
||||
substrs = ['CircleCategory is not enabled'])
|
||||
|
||||
self.expect("frame variable c1 r1 c_ptr r_ptr",
|
||||
self.expect("frame variable c1 r_ptr",
|
||||
substrs = ['AShape',
|
||||
'AShape',
|
||||
'AShape',
|
||||
'ARectangleStar'])
|
||||
|
||||
# check that filters work into categories
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
#include <stdint.h>
|
||||
|
||||
struct Shape
|
||||
{};
|
||||
{
|
||||
bool dummy;
|
||||
Shape() : dummy(true) {}
|
||||
};
|
||||
|
||||
struct Rectangle : public Shape {
|
||||
int w;
|
||||
|
|
|
@ -128,20 +128,6 @@ class ObjCDataFormatterTestCase(TestBase):
|
|||
|
||||
self.runCmd("type summary add --summary-string \"a test\" MyClass")
|
||||
|
||||
self.expect("frame variable object2",
|
||||
substrs = ['a test']);
|
||||
|
||||
self.expect("frame variable *object2",
|
||||
substrs = ['a test']);
|
||||
|
||||
self.expect("frame variable object",
|
||||
substrs = ['a test']);
|
||||
|
||||
self.expect("frame variable *object",
|
||||
substrs = ['a test']);
|
||||
|
||||
self.runCmd("type summary add --summary-string \"a test\" MyClass -C no")
|
||||
|
||||
self.expect("frame variable *object2",
|
||||
substrs = ['*object2 = {',
|
||||
'MyClass = a test',
|
||||
|
|
|
@ -1255,18 +1255,9 @@ def function (valobj,dict):<br/>
|
|||
<li>If this object is a reference, and there is a
|
||||
formatter for the referred type that does not skip
|
||||
references, use it</li>
|
||||
<li>If this object is an Objective-C class with a parent
|
||||
class, look at the parent class (and parent of parent,
|
||||
...). This phase can be based upon the actual type of
|
||||
the object as inferred by the value of its <code>isa</code>
|
||||
pointer, or upon the debugging information inferred by the
|
||||
debugger. The user can use the dynamic typing settings to
|
||||
elect one or the other behavior.</li>
|
||||
<li>If this object is a C++ class with base classes,
|
||||
look at base classes (and bases of bases, ...)</li>
|
||||
<li>If this object is a C++ class with virtual base
|
||||
classes, look at the virtual base classes (and bases
|
||||
of bases, ...)</li>
|
||||
<li>If this object is an Objective-C class and dynamic types are enabled,
|
||||
look for a formatter for the dynamic type of the object. If dynamic types are disabled,
|
||||
or the search failed, look for a formatter for the declared type of the object</li>
|
||||
<li>If this object's type is a typedef, go through
|
||||
typedef hierarchy (LLDB might not be able to do this if
|
||||
the compiler has not emitted enough information. If the
|
||||
|
@ -1274,7 +1265,8 @@ def function (valobj,dict):<br/>
|
|||
missing, type cascading will not work. The
|
||||
<a href="http://clang.llvm.org/">clang compiler</a>,
|
||||
part of the LLVM project, emits the correct debugging
|
||||
information for LLDB to cascade)</li>
|
||||
information for LLDB to cascade). If at any level of the hierarchy
|
||||
there is a valid formatter that can cascade, use it.</li>
|
||||
<li>If everything has failed, repeat the above search,
|
||||
looking for regular expressions instead of exact
|
||||
matches</li>
|
||||
|
@ -1284,6 +1276,11 @@ def function (valobj,dict):<br/>
|
|||
in other categories). If nothing was found in the current category, the next
|
||||
enabled category is scanned according to the same algorithm. If there are no
|
||||
more enabled categories, the search has failed.</p>
|
||||
<p><font color=red>Warning</font>: previous versions of LLDB defined cascading to mean
|
||||
not only going through typedef chains, but also through inheritance chains.
|
||||
This feature has been removed since it significantly degrades performance.
|
||||
You need to set up your formatters for every type in inheritance chains to which
|
||||
you want the formatter to apply.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue