forked from OSchip/llvm-project
<rdar://problem/14071463>
SVN r189964 provided a sample Python script to inspect unordered(multi){set|map} with synthetic children, contribued by Jared Grubb This checkin converts that sample script to a C++ provider built into LLDB A test case is also provided llvm-svn: 190564
This commit is contained in:
parent
872ac4b5f0
commit
e2e220a805
|
@ -767,6 +767,23 @@ public:
|
|||
lldb::ValueObjectSP
|
||||
GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &idxs,
|
||||
size_t* index_of_error = NULL);
|
||||
|
||||
// this will always create the children if necessary
|
||||
lldb::ValueObjectSP
|
||||
GetChildAtNamePath (const std::initializer_list<ConstString> &names,
|
||||
ConstString* name_of_error = NULL);
|
||||
|
||||
lldb::ValueObjectSP
|
||||
GetChildAtNamePath (const std::vector<ConstString> &names,
|
||||
ConstString* name_of_error = NULL);
|
||||
|
||||
lldb::ValueObjectSP
|
||||
GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
|
||||
ConstString* name_of_error = NULL);
|
||||
|
||||
lldb::ValueObjectSP
|
||||
GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names,
|
||||
ConstString* name_of_error = NULL);
|
||||
|
||||
virtual lldb::ValueObjectSP
|
||||
GetChildMemberWithName (const ConstString &name, bool can_create);
|
||||
|
|
|
@ -868,6 +868,39 @@ namespace lldb_private {
|
|||
|
||||
SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
|
||||
|
||||
class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
|
||||
{
|
||||
public:
|
||||
LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
|
||||
|
||||
virtual size_t
|
||||
CalculateNumChildren ();
|
||||
|
||||
virtual lldb::ValueObjectSP
|
||||
GetChildAtIndex (size_t idx);
|
||||
|
||||
virtual bool
|
||||
Update();
|
||||
|
||||
virtual bool
|
||||
MightHaveChildren ();
|
||||
|
||||
virtual size_t
|
||||
GetIndexOfChildWithName (const ConstString &name);
|
||||
|
||||
virtual
|
||||
~LibcxxStdUnorderedMapSyntheticFrontEnd ();
|
||||
private:
|
||||
|
||||
ValueObject* m_tree;
|
||||
size_t m_num_elements;
|
||||
ValueObject* m_next_element;
|
||||
std::map<size_t,lldb::ValueObjectSP> m_children;
|
||||
std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache;
|
||||
};
|
||||
|
||||
SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
|
||||
|
||||
} // namespace formatters
|
||||
} // namespace lldb_private
|
||||
|
||||
|
|
|
@ -531,11 +531,11 @@
|
|||
944372DD171F6B4300E57C32 /* RegisterContextDummy.h in Headers */ = {isa = PBXBuildFile; fileRef = 944372DB171F6B4300E57C32 /* RegisterContextDummy.h */; };
|
||||
9443B122140C18C40013457C /* SBData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9443B121140C18C10013457C /* SBData.cpp */; };
|
||||
9443B123140C26AB0013457C /* SBData.h in Headers */ = {isa = PBXBuildFile; fileRef = 9443B120140C18A90013457C /* SBData.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9452573A16262D0200325455 /* SBDeclaration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9452573916262D0200325455 /* SBDeclaration.cpp */; };
|
||||
9456F2241616671900656F91 /* DynamicLibrary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9456F2211616644B00656F91 /* DynamicLibrary.cpp */; };
|
||||
945759671534941F005A9070 /* PlatformPOSIX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945759651534941F005A9070 /* PlatformPOSIX.cpp */; };
|
||||
945759681534941F005A9070 /* PlatformPOSIX.h in Headers */ = {isa = PBXBuildFile; fileRef = 945759661534941F005A9070 /* PlatformPOSIX.h */; };
|
||||
945E8D80152F6AB40019BCCD /* StreamGDBRemote.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945E8D7F152F6AB40019BCCD /* StreamGDBRemote.cpp */; };
|
||||
9452573A16262D0200325455 /* SBDeclaration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9452573916262D0200325455 /* SBDeclaration.cpp */; };
|
||||
9456F2241616671900656F91 /* DynamicLibrary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9456F2211616644B00656F91 /* DynamicLibrary.cpp */; };
|
||||
9461569A14E358A6003A195C /* SBTypeFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568A14E35621003A195C /* SBTypeFilter.cpp */; };
|
||||
9461569B14E358A6003A195C /* SBTypeFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568B14E35621003A195C /* SBTypeFormat.cpp */; };
|
||||
9461569C14E358A6003A195C /* SBTypeSummary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568C14E35621003A195C /* SBTypeSummary.cpp */; };
|
||||
|
@ -549,7 +549,6 @@
|
|||
947A1D651616476B0017C8D1 /* CommandObjectPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 947A1D631616476A0017C8D1 /* CommandObjectPlugin.h */; };
|
||||
949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */; };
|
||||
94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */; };
|
||||
94E829CA152D33C1006F96A3 /* lldb-platform in Resources */ = {isa = PBXBuildFile; fileRef = 26DC6A101337FE6900FF7998 /* lldb-platform */; };
|
||||
94BA8B6D176F8C9B005A91B5 /* Range.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94BA8B6C176F8C9B005A91B5 /* Range.cpp */; };
|
||||
94BA8B70176F97CE005A91B5 /* CommandHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94BA8B6F176F97CE005A91B5 /* CommandHistory.cpp */; };
|
||||
94CB255B16B069770059775D /* CXXFormatterFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB255716B069770059775D /* CXXFormatterFunctions.cpp */; };
|
||||
|
@ -571,7 +570,9 @@
|
|||
94D6A0AA16CEB55F00833B6E /* NSArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A716CEB55F00833B6E /* NSArray.cpp */; };
|
||||
94D6A0AB16CEB55F00833B6E /* NSDictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */; };
|
||||
94D6A0AC16CEB55F00833B6E /* NSSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A916CEB55F00833B6E /* NSSet.cpp */; };
|
||||
94E829CA152D33C1006F96A3 /* lldb-platform in Resources */ = {isa = PBXBuildFile; fileRef = 26DC6A101337FE6900FF7998 /* lldb-platform */; };
|
||||
94EA1D5C15E6C9B400D4171A /* PythonDataObjects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94EA1D5B15E6C9B400D4171A /* PythonDataObjects.cpp */; };
|
||||
94EA27CE17DE91750070F505 /* LibCxxUnorderedMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94EA27CD17DE91750070F505 /* LibCxxUnorderedMap.cpp */; };
|
||||
94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */; };
|
||||
9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; };
|
||||
|
@ -1573,16 +1574,16 @@
|
|||
944372DB171F6B4300E57C32 /* RegisterContextDummy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDummy.h; path = Utility/RegisterContextDummy.h; sourceTree = "<group>"; };
|
||||
9443B120140C18A90013457C /* SBData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBData.h; path = include/lldb/API/SBData.h; sourceTree = "<group>"; };
|
||||
9443B121140C18C10013457C /* SBData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBData.cpp; path = source/API/SBData.cpp; sourceTree = "<group>"; };
|
||||
945759651534941F005A9070 /* PlatformPOSIX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformPOSIX.cpp; path = POSIX/PlatformPOSIX.cpp; sourceTree = "<group>"; };
|
||||
945759661534941F005A9070 /* PlatformPOSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformPOSIX.h; path = POSIX/PlatformPOSIX.h; sourceTree = "<group>"; };
|
||||
945E8D7D152F6AA80019BCCD /* StreamGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamGDBRemote.h; path = include/lldb/Core/StreamGDBRemote.h; sourceTree = "<group>"; };
|
||||
945E8D7F152F6AB40019BCCD /* StreamGDBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StreamGDBRemote.cpp; path = source/Core/StreamGDBRemote.cpp; sourceTree = "<group>"; };
|
||||
944DC3481774C99000D7D884 /* python-swigsafecast.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-swigsafecast.swig"; sourceTree = "<group>"; };
|
||||
9452573616262CD000325455 /* SBDeclaration.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBDeclaration.i; sourceTree = "<group>"; };
|
||||
9452573816262CEF00325455 /* SBDeclaration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBDeclaration.h; path = include/lldb/API/SBDeclaration.h; sourceTree = "<group>"; };
|
||||
9452573916262D0200325455 /* SBDeclaration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBDeclaration.cpp; path = source/API/SBDeclaration.cpp; sourceTree = "<group>"; };
|
||||
9456F2211616644B00656F91 /* DynamicLibrary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLibrary.cpp; sourceTree = "<group>"; };
|
||||
9456F2231616645A00656F91 /* DynamicLibrary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DynamicLibrary.h; path = include/lldb/Host/DynamicLibrary.h; sourceTree = "<group>"; };
|
||||
945759651534941F005A9070 /* PlatformPOSIX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformPOSIX.cpp; path = POSIX/PlatformPOSIX.cpp; sourceTree = "<group>"; };
|
||||
945759661534941F005A9070 /* PlatformPOSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformPOSIX.h; path = POSIX/PlatformPOSIX.h; sourceTree = "<group>"; };
|
||||
945E8D7D152F6AA80019BCCD /* StreamGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamGDBRemote.h; path = include/lldb/Core/StreamGDBRemote.h; sourceTree = "<group>"; };
|
||||
945E8D7F152F6AB40019BCCD /* StreamGDBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StreamGDBRemote.cpp; path = source/Core/StreamGDBRemote.cpp; sourceTree = "<group>"; };
|
||||
9461568614E355F2003A195C /* SBTypeFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeFilter.h; path = include/lldb/API/SBTypeFilter.h; sourceTree = "<group>"; };
|
||||
9461568714E355F2003A195C /* SBTypeFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeFormat.h; path = include/lldb/API/SBTypeFormat.h; sourceTree = "<group>"; };
|
||||
9461568814E355F2003A195C /* SBTypeSummary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeSummary.h; path = include/lldb/API/SBTypeSummary.h; sourceTree = "<group>"; };
|
||||
|
@ -1647,6 +1648,7 @@
|
|||
94E367CE140C4EEA001C7A5A /* python-typemaps.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-typemaps.swig"; sourceTree = "<group>"; };
|
||||
94EA1D5A15E6C99B00D4171A /* PythonDataObjects.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PythonDataObjects.h; path = include/lldb/Interpreter/PythonDataObjects.h; sourceTree = "<group>"; };
|
||||
94EA1D5B15E6C9B400D4171A /* PythonDataObjects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PythonDataObjects.cpp; path = source/Interpreter/PythonDataObjects.cpp; sourceTree = "<group>"; };
|
||||
94EA27CD17DE91750070F505 /* LibCxxUnorderedMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxUnorderedMap.cpp; path = source/DataFormatters/LibCxxUnorderedMap.cpp; sourceTree = "<group>"; };
|
||||
94EBAC8313D9EE26009BA64E /* PythonPointer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PythonPointer.h; path = include/lldb/Utility/PythonPointer.h; sourceTree = "<group>"; };
|
||||
94FA3DDD1405D4E500833217 /* ValueObjectConstResultChild.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResultChild.h; path = include/lldb/Core/ValueObjectConstResultChild.h; sourceTree = "<group>"; };
|
||||
94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResultChild.cpp; path = source/Core/ValueObjectConstResultChild.cpp; sourceTree = "<group>"; };
|
||||
|
@ -3429,60 +3431,6 @@
|
|||
name = POSIX;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
940DB8C416EA64D400D3C2F1 /* lldb-perf */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
940DB8C616EA654E00D3C2F1 /* darwin */,
|
||||
940DB8C516EA654900D3C2F1 /* lib */,
|
||||
);
|
||||
name = "lldb-perf";
|
||||
path = "tools/lldb-perf";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
940DB8C516EA654900D3C2F1 /* lib */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
940DB8CA16EA66FB00D3C2F1 /* Gauge.h */,
|
||||
940DB8CE16EA670C00D3C2F1 /* Measurement.h */,
|
||||
940DB8D116EA671800D3C2F1 /* MemoryGauge.cpp */,
|
||||
940DB8D216EA671800D3C2F1 /* MemoryGauge.h */,
|
||||
940DB8D516EA672200D3C2F1 /* Metric.cpp */,
|
||||
940DB8D616EA672200D3C2F1 /* Metric.h */,
|
||||
940DB8D916EA672D00D3C2F1 /* TestCase.cpp */,
|
||||
940DB8DA16EA672D00D3C2F1 /* TestCase.h */,
|
||||
940DB8DD16EA673800D3C2F1 /* Timer.cpp */,
|
||||
940DB8DE16EA673800D3C2F1 /* Timer.h */,
|
||||
940DB8E116EA674000D3C2F1 /* Xcode.cpp */,
|
||||
940DB8E216EA674000D3C2F1 /* Xcode.h */,
|
||||
);
|
||||
path = lib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
940DB8C616EA654E00D3C2F1 /* darwin */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
940DB8FB16EA84BF00D3C2F1 /* formatters */,
|
||||
940DB8C716EA655400D3C2F1 /* sketch */,
|
||||
);
|
||||
path = darwin;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
940DB8C716EA655400D3C2F1 /* sketch */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
940DB8E616EA709400D3C2F1 /* main.cpp */,
|
||||
);
|
||||
path = sketch;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
940DB8FB16EA84BF00D3C2F1 /* formatters */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
94DB60F016EA888A00459D9E /* main.cpp */,
|
||||
);
|
||||
path = formatters;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
94CB255616B0683B0059775D /* DataFormatters */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -3502,6 +3450,7 @@
|
|||
94D0B10A16D5535900EA9C70 /* LibCxx.cpp */,
|
||||
94CD704F16F8DF1C00CF1E42 /* LibCxxList.cpp */,
|
||||
94CD705116F8F5BC00CF1E42 /* LibCxxMap.cpp */,
|
||||
94EA27CD17DE91750070F505 /* LibCxxUnorderedMap.cpp */,
|
||||
94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */,
|
||||
94D6A0A716CEB55F00833B6E /* NSArray.cpp */,
|
||||
94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */,
|
||||
|
@ -4327,6 +4276,7 @@
|
|||
94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */,
|
||||
262D24E613FB8710002D1960 /* RegisterContextMemory.cpp in Sources */,
|
||||
26F4A21C13FBA31A0064B613 /* ThreadMemory.cpp in Sources */,
|
||||
94EA27CE17DE91750070F505 /* LibCxxUnorderedMap.cpp in Sources */,
|
||||
266DFE9713FD656E00D0C574 /* OperatingSystem.cpp in Sources */,
|
||||
26954EBE1401EE8B00294D09 /* DynamicRegisterInfo.cpp in Sources */,
|
||||
26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */,
|
||||
|
|
|
@ -595,6 +595,86 @@ ValueObject::GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &
|
|||
return root;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
ValueObject::GetChildAtNamePath (const std::initializer_list<ConstString> &names,
|
||||
ConstString* name_of_error)
|
||||
{
|
||||
if (names.size() == 0)
|
||||
return GetSP();
|
||||
ValueObjectSP root(GetSP());
|
||||
for (ConstString name : names)
|
||||
{
|
||||
root = root->GetChildMemberWithName(name, true);
|
||||
if (!root)
|
||||
{
|
||||
if (name_of_error)
|
||||
*name_of_error = name;
|
||||
return root;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
ValueObject::GetChildAtNamePath (const std::vector<ConstString> &names,
|
||||
ConstString* name_of_error)
|
||||
{
|
||||
if (names.size() == 0)
|
||||
return GetSP();
|
||||
ValueObjectSP root(GetSP());
|
||||
for (ConstString name : names)
|
||||
{
|
||||
root = root->GetChildMemberWithName(name, true);
|
||||
if (!root)
|
||||
{
|
||||
if (name_of_error)
|
||||
*name_of_error = name;
|
||||
return root;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
|
||||
ConstString* name_of_error)
|
||||
{
|
||||
if (names.size() == 0)
|
||||
return GetSP();
|
||||
ValueObjectSP root(GetSP());
|
||||
for (std::pair<ConstString, bool> name : names)
|
||||
{
|
||||
root = root->GetChildMemberWithName(name.first, name.second);
|
||||
if (!root)
|
||||
{
|
||||
if (name_of_error)
|
||||
*name_of_error = name.first;
|
||||
return root;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
ValueObject::GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names,
|
||||
ConstString* name_of_error)
|
||||
{
|
||||
if (names.size() == 0)
|
||||
return GetSP();
|
||||
ValueObjectSP root(GetSP());
|
||||
for (std::pair<ConstString, bool> name : names)
|
||||
{
|
||||
root = root->GetChildMemberWithName(name.first, name.second);
|
||||
if (!root)
|
||||
{
|
||||
if (name_of_error)
|
||||
*name_of_error = name.first;
|
||||
return root;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
size_t
|
||||
ValueObject::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
|
|
|
@ -632,7 +632,8 @@ FormatManager::LoadLibcxxFormatters()
|
|||
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true);
|
||||
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true);
|
||||
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true);
|
||||
|
||||
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true);
|
||||
|
||||
libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
|
||||
SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
|
||||
"lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
|
||||
|
@ -650,6 +651,7 @@ FormatManager::LoadLibcxxFormatters()
|
|||
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true);
|
||||
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true);
|
||||
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true);
|
||||
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true);
|
||||
|
||||
stl_summary_flags.SetSkipPointers(true);
|
||||
AddStringSummary(libcxx_category_sp, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})}", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
//===-- LibCxxUnorderedMap.cpp -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/lldb-python.h"
|
||||
|
||||
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
|
||||
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/Core/ValueObjectConstResult.h"
|
||||
#include "lldb/Host/Endian.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
#include "lldb/Target/ObjCLanguageRuntime.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::formatters;
|
||||
|
||||
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get()),
|
||||
m_tree(NULL),
|
||||
m_num_elements(0),
|
||||
m_next_element(nullptr),
|
||||
m_children(),
|
||||
m_elements_cache()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
if (m_num_elements != UINT32_MAX)
|
||||
return m_num_elements;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
if (idx >= CalculateNumChildren())
|
||||
return lldb::ValueObjectSP();
|
||||
if (m_tree == NULL)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
auto cached = m_children.find(idx);
|
||||
if (cached != m_children.end())
|
||||
return cached->second;
|
||||
|
||||
while (idx >= m_elements_cache.size())
|
||||
{
|
||||
if (m_next_element == nullptr)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
Error error;
|
||||
ValueObjectSP node_sp = m_next_element->Dereference(error);
|
||||
if (!node_sp || error.Fail())
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
ValueObjectSP value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
|
||||
ValueObjectSP hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
|
||||
if (!hash_sp || !value_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
m_elements_cache.push_back({value_sp.get(),hash_sp->GetValueAsUnsigned(0)});
|
||||
m_next_element = node_sp->GetChildMemberWithName(ConstString("__next_"),true).get();
|
||||
if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
|
||||
m_next_element = nullptr;
|
||||
}
|
||||
|
||||
std::pair<ValueObject*, uint64_t> val_hash = m_elements_cache[idx];
|
||||
if (!val_hash.first)
|
||||
return lldb::ValueObjectSP();
|
||||
StreamString stream;
|
||||
stream.Printf("[%zu]",idx);
|
||||
DataExtractor data;
|
||||
val_hash.first->GetData(data);
|
||||
ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock();
|
||||
return val_hash.first->CreateValueObjectFromData(stream.GetData(),
|
||||
data,
|
||||
exe_ctx,
|
||||
val_hash.first->GetClangType());
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::Update()
|
||||
{
|
||||
m_num_elements = UINT32_MAX;
|
||||
m_next_element = nullptr;
|
||||
m_elements_cache.clear();
|
||||
m_children.clear();
|
||||
ValueObjectSP table_sp = m_backend.GetChildMemberWithName(ConstString("__table_"), true);
|
||||
if (!table_sp)
|
||||
return false;
|
||||
ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath({ConstString("__p2_"),ConstString("__first_")});
|
||||
if (!num_elements_sp)
|
||||
return false;
|
||||
m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
|
||||
m_tree = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
|
||||
if (m_num_elements > 0)
|
||||
m_next_element = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
return ExtractIndexFromString(name.GetCString());
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::~LibcxxStdUnorderedMapSyntheticFrontEnd ()
|
||||
{}
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp));
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
LEVEL = ../../../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
|
||||
CXXFLAGS += -stdlib=libc++ -O0 -std=c++11
|
||||
LDFLAGS += -stdlib=libc++
|
|
@ -0,0 +1,75 @@
|
|||
"""
|
||||
Test lldb data formatter subsystem.
|
||||
"""
|
||||
|
||||
import os, time
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
import lldbutil
|
||||
|
||||
class LibcxxMultiMapDataFormatterTestCase(TestBase):
|
||||
|
||||
mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libcxx", "unordered")
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
@dsym_test
|
||||
def test_with_dsym_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDsym()
|
||||
self.data_formatter_commands()
|
||||
|
||||
@skipIfLinux # No standard locations for libc++ on Linux, so skip for now
|
||||
@dwarf_test
|
||||
def test_with_dwarf_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDwarf()
|
||||
self.data_formatter_commands()
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
|
||||
def look_for_content_and_continue(self,var_name,substrs):
|
||||
self.expect( ("frame variable %s" % var_name), substrs )
|
||||
self.runCmd("continue")
|
||||
|
||||
def data_formatter_commands(self):
|
||||
"""Test that that file and class static variables display correctly."""
|
||||
self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
|
||||
|
||||
lldbutil.run_break_set_by_source_regexp (self, "Set break point at this line.")
|
||||
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs = ['stopped',
|
||||
'stop reason = breakpoint'])
|
||||
|
||||
# This is the function to remove the custom formats in order to have a
|
||||
# clean slate for the next test case.
|
||||
def cleanup():
|
||||
self.runCmd('type format clear', check=False)
|
||||
self.runCmd('type summary clear', check=False)
|
||||
self.runCmd('type filter clear', check=False)
|
||||
self.runCmd('type synth clear', check=False)
|
||||
self.runCmd("settings set target.max-children-count 256", check=False)
|
||||
|
||||
# Execute the cleanup function during test case tear down.
|
||||
self.addTearDownHook(cleanup)
|
||||
|
||||
self.expect('image list', substrs = self.getLibcPlusPlusLibs())
|
||||
|
||||
self.look_for_content_and_continue("map",['size=5 {,''hello','world','this','is','me'])
|
||||
self.look_for_content_and_continue("mmap",['size=6 {','first = 3','second = "this"','first = 2','second = "hello"'])
|
||||
self.look_for_content_and_continue("iset",['size=5 {','[0] = 5','[2] = 3','[3] = 2'])
|
||||
self.look_for_content_and_continue("sset",['size=5 {','[0] = "is"','[1] = "world"','[4] = "hello"'])
|
||||
self.look_for_content_and_continue("imset",['size=6 {','[0] = 3','[1] = 3','[2] = 3','[4] = 2','[5] = 1'])
|
||||
self.look_for_content_and_continue("smset",['size=5 {','[0] = "is"','[1] = "is"','[2] = "world"','[3] = "world"'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
|
@ -0,0 +1,84 @@
|
|||
#include <string>
|
||||
#ifdef _LIBCPP_INLINE_VISIBILITY
|
||||
#undef _LIBCPP_INLINE_VISIBILITY
|
||||
#endif
|
||||
#define _LIBCPP_INLINE_VISIBILITY
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
using std::string;
|
||||
|
||||
#define intstr_map std::unordered_map<int, string>
|
||||
#define intstr_mmap std::unordered_multimap<int, string>
|
||||
|
||||
#define int_set std::unordered_set<int>
|
||||
#define str_set std::unordered_set<string>
|
||||
#define int_mset std::unordered_multiset<int>
|
||||
#define str_mset std::unordered_multiset<string>
|
||||
|
||||
int g_the_foo = 0;
|
||||
|
||||
int thefoo_rw(int arg = 1)
|
||||
{
|
||||
if (arg < 0)
|
||||
arg = 0;
|
||||
if (!arg)
|
||||
arg = 1;
|
||||
g_the_foo += arg;
|
||||
return g_the_foo;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
intstr_map map;
|
||||
map.emplace(1,"hello");
|
||||
map.emplace(2,"world");
|
||||
map.emplace(3,"this");
|
||||
map.emplace(4,"is");
|
||||
map.emplace(5,"me");
|
||||
thefoo_rw(); // Set break point at this line.
|
||||
|
||||
intstr_mmap mmap;
|
||||
mmap.emplace(1,"hello");
|
||||
mmap.emplace(2,"hello");
|
||||
mmap.emplace(2,"world");
|
||||
mmap.emplace(3,"this");
|
||||
mmap.emplace(3,"this");
|
||||
mmap.emplace(3,"this");
|
||||
thefoo_rw(); // Set break point at this line.
|
||||
|
||||
int_set iset;
|
||||
iset.emplace(1);
|
||||
iset.emplace(2);
|
||||
iset.emplace(3);
|
||||
iset.emplace(4);
|
||||
iset.emplace(5);
|
||||
thefoo_rw(); // Set break point at this line.
|
||||
|
||||
str_set sset;
|
||||
sset.emplace("hello");
|
||||
sset.emplace("world");
|
||||
sset.emplace("this");
|
||||
sset.emplace("is");
|
||||
sset.emplace("me");
|
||||
thefoo_rw(); // Set break point at this line.
|
||||
|
||||
int_mset imset;
|
||||
imset.emplace(1);
|
||||
imset.emplace(2);
|
||||
imset.emplace(2);
|
||||
imset.emplace(3);
|
||||
imset.emplace(3);
|
||||
imset.emplace(3);
|
||||
thefoo_rw(); // Set break point at this line.
|
||||
|
||||
str_mset smset;
|
||||
smset.emplace("hello");
|
||||
smset.emplace("world");
|
||||
smset.emplace("world");
|
||||
smset.emplace("is");
|
||||
smset.emplace("is");
|
||||
thefoo_rw(); // Set break point at this line.
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue