| <?xml version="1.0" encoding="utf-8" ?> |
| <AutoVisualizer |
| xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> |
| |
| <!-- libc++'s __compressed_pair is an internal type used pervasively for |
| doing the empty base class optimization. |
| |
| __compressed_pair<U,V> derives from __compressed_pair_elem<U,0> and |
| __compressed_pair_elem<V,1>. __compressed_pair_elem<T> is specialized on |
| a 3rd template parameter: |
| * if T is empty and non-final the 3rd param is 1 and it derives from T |
| * else it has a member variable __value_ of type T |
| --> |
| <Type Name="std::__1::__compressed_pair_elem<*,*,0>"> |
| <DisplayString>{__value_}</DisplayString> |
| <Expand> |
| <ExpandedItem>__value_</ExpandedItem> |
| </Expand> |
| </Type> |
| <Type Name="std::__1::__compressed_pair_elem<*,*,1>"> |
| <DisplayString>{*($T1*)this}</DisplayString> |
| <Expand> |
| <ExpandedItem>*($T1*)this</ExpandedItem> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::array<*,*>"> |
| <DisplayString>{{ size={$T2} }}</DisplayString> |
| <Expand> |
| <ArrayItems> |
| <Size>$T2</Size> |
| <ValuePointer>__elems_</ValuePointer> |
| </ArrayItems> |
| </Expand> |
| </Type> |
| |
| <!--libc++'s short string optimization: |
| A basic_string is 3 size_t words long. In the "alternate string layout" |
| that we use, they are: pointer to data, size, capacity. |
| (In the normal layout, it's capacity, size, data instead.) |
| If a string is short enough that it fits in these three size_ts instead, |
| the string data is stored inline in these 3 words, with the last byte of |
| the storage storing the length of the string. |
| The highest bit of the "capacity" word is set for normal, "long" strings, |
| and that bit needs to be masked out to know the real capacity. |
| If this bit is not set, the string data is stored inline. |
| (In the normal layout, if the lowest bit in the first byte is set, |
| it's a "long" string, requiring a long string to always have even |
| capacity. A short string here stores its length in the first byte |
| and the inline data in the remaining storage.) |
| --> |
| |
| <Type Name="std::__1::basic_string<char,*>"> |
| <!--<Intrinsic Name="is_long" |
| Expression="((__rep*)&__r_)->__s.__size_ & 0x80" />--> |
| <!-- The above doesn't work because of https://llvm.org/PR41615 |
| TODO(thakis): Now that we have clang r362038, try the above approach |
| again. |
| The below assumes the alternate string layout and little endianness :/ |
| --> |
| <Intrinsic Name="is_long" |
| Expression="*(((char*)this) + 3*sizeof(size_t) - 1) & 0x80" /> |
| <DisplayString Condition="is_long()">{*(char**)this}</DisplayString> |
| <DisplayString Condition="!is_long()">{(char*)this}</DisplayString> |
| <StringView Condition="is_long()">*(char**)this</StringView> |
| <StringView Condition="!is_long()">(char*)this</StringView> |
| <Expand> |
| <Item Name="[size]" Condition="is_long()" |
| ExcludeView="simple">((size_t*)this)[1]</Item> |
| <Item Name="[size]" Condition="!is_long()" |
| ExcludeView="simple">*(((char*)this) + 3*sizeof(size_t) - 1)</Item> |
| <Item Name="[capacity]" Condition="is_long()" ExcludeView="simple"> |
| ((size_t*)this)[2] & (~((size_t)0) >> 1) |
| </Item> |
| <Item Name="[capacity]" Condition="!is_long()" |
| ExcludeView="simple">22</Item> |
| <ArrayItems> |
| <Size Condition="is_long()">((size_t*)this)[1]</Size> |
| <Size Condition="!is_long()"> |
| *(((char*)this) + 3*sizeof(size_t) - 1) |
| </Size> |
| <ValuePointer Condition="is_long()">*(char**)this</ValuePointer> |
| <ValuePointer Condition="!is_long()">(char*)this</ValuePointer> |
| </ArrayItems> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::basic_string<wchar_t,*>"> |
| <Intrinsic Name="is_long" |
| Expression="*(((char*)this) + 3*sizeof(size_t) - 1) & 0x80" /> |
| <DisplayString Condition="is_long()">{*(wchar_t**)this}</DisplayString> |
| <DisplayString Condition="!is_long()">{(wchar_t*)this}</DisplayString> |
| <StringView Condition="is_long()">*(wchar_t**)this</StringView> |
| <StringView Condition="!is_long()">(wchar_t*)this</StringView> |
| <Expand> |
| <Item Name="[size]" Condition="is_long()" |
| ExcludeView="simple">((size_t*)this)[1]</Item> |
| <Item Name="[size]" Condition="!is_long()" |
| ExcludeView="simple">*(((char*)this) + 3*sizeof(size_t) - 1)</Item> |
| <Item Name="[capacity]" Condition="is_long()" ExcludeView="simple"> |
| ((size_t*)this)[2] & (~((size_t)0) >> 1) |
| </Item> |
| <Item Name="[capacity]" Condition="!is_long()" |
| ExcludeView="simple">10</Item> |
| <ArrayItems> |
| <Size Condition="is_long()">((size_t*)this)[1]</Size> |
| <Size Condition="!is_long()"> |
| *(((char*)this) + 3*sizeof(size_t) - 1) |
| </Size> |
| <ValuePointer Condition="is_long()">*(wchar_t**)this</ValuePointer> |
| <ValuePointer Condition="!is_long()">(wchar_t*)this</ValuePointer> |
| </ArrayItems> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::deque<*,*>"> |
| <Intrinsic Name="size" Expression="*(size_type*)&__size_" /> |
| <Intrinsic Name="block_size" |
| Expression="sizeof($T1) < 256 ? 4096 / sizeof($T1) : 16" /> |
| <DisplayString>{{ size={size()} }}</DisplayString> |
| <Expand> |
| <IndexListItems> |
| <Size>size()</Size> |
| <ValueNode> |
| *(*(__map_.__begin_ + ($i + __start_) / block_size()) + |
| ($i + __start_) % block_size()) |
| </ValueNode> |
| </IndexListItems> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::forward_list<*>"> |
| <Intrinsic Name="head" |
| Expression="((__node_pointer)&__before_begin_)->__next_" /> |
| <DisplayString Condition="head() == 0">empty</DisplayString> |
| <DisplayString Condition="head() != 0">non-empty</DisplayString> |
| <Expand> |
| <LinkedListItems> |
| <HeadPointer>head()</HeadPointer> |
| <NextPointer>__next_</NextPointer> |
| <ValueNode>__value_</ValueNode> |
| </LinkedListItems> |
| </Expand> |
| </Type> |
| |
| <!-- Note: Not in __1! But will win over the one in stl.natvis --> |
| <Type Name="std::initializer_list<*>"> |
| <DisplayString>{{ size={__size_} }}</DisplayString> |
| <Expand> |
| <ArrayItems> |
| <Size>__size_</Size> |
| <ValuePointer>__begin_</ValuePointer> |
| </ArrayItems> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::list<*>"> |
| <Intrinsic Name="size" Expression="*(size_type*)&__size_alloc_" /> |
| <DisplayString>{{ size={size()} }}</DisplayString> |
| <Expand> |
| <LinkedListItems> |
| <Size>size()</Size> |
| <HeadPointer>__end_.__next_</HeadPointer> |
| <NextPointer>__next_</NextPointer> |
| <ValueNode> |
| ((std::__1::list<$T1,$T2>::__node_pointer)this) |
| ->__value_ |
| </ValueNode> |
| </LinkedListItems> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::map<*>"> |
| <Intrinsic Name="size" Expression="*(size_type*)&__tree_.__pair3_" /> |
| <DisplayString>{{ size={size()} }}</DisplayString> |
| <Expand> |
| <Item Name="[size]">size()</Item> |
| <TreeItems> |
| <Size>size()</Size> |
| <HeadPointer> |
| ((__node_pointer)&__tree_.__pair1_)->__left_ |
| </HeadPointer> |
| <LeftPointer> |
| ((std::__1::map<$T1,$T2,$T3,$T4>::__node_pointer)this) |
| ->__left_ |
| </LeftPointer> |
| <RightPointer> |
| ((std::__1::map<$T1,$T2,$T3,$T4>::__node_pointer)this) |
| ->__right_ |
| </RightPointer> |
| <ValueNode> |
| ((std::__1::map<$T1,$T2,$T3,$T4>::__node_pointer)this) |
| ->__value_.__cc |
| </ValueNode> |
| </TreeItems> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::multimap<*>"> |
| <Intrinsic Name="size" Expression="*(size_type*)&__tree_.__pair3_" /> |
| <DisplayString>{{ size={size()} }}</DisplayString> |
| <Expand> |
| <Item Name="[size]">size()</Item> |
| <TreeItems> |
| <Size>size()</Size> |
| <HeadPointer> |
| ((__node_pointer)&__tree_.__pair1_)->__left_ |
| </HeadPointer> |
| <LeftPointer> |
| ((std::__1::multimap<$T1,$T2,$T3,$T4>::__node_pointer)this) |
| ->__left_ |
| </LeftPointer> |
| <RightPointer> |
| ((std::__1::multimap<$T1,$T2,$T3,$T4>::__node_pointer)this) |
| ->__right_ |
| </RightPointer> |
| <ValueNode> |
| ((std::__1::multimap<$T1,$T2,$T3,$T4>::__node_pointer)this) |
| ->__value_.__cc |
| </ValueNode> |
| </TreeItems> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::multiset<*>"> |
| <Intrinsic Name="size" Expression="*(size_type*)&__tree_.__pair3_" /> |
| <DisplayString>{{ size={size()} }}</DisplayString> |
| <Expand> |
| <Item Name="[size]">size()</Item> |
| <TreeItems> |
| <Size>size()</Size> |
| <HeadPointer> |
| ((__base::__node_pointer)&__tree_.__pair1_)->__left_ |
| </HeadPointer> |
| <LeftPointer> |
| ((std::__1::multiset<$T1,$T2,$T3>::__base::__node_pointer)this) |
| ->__left_ |
| </LeftPointer> |
| <RightPointer> |
| ((std::__1::multiset<$T1,$T2,$T3>::__base::__node_pointer)this) |
| ->__right_ |
| </RightPointer> |
| <ValueNode> |
| ((std::__1::multiset<$T1,$T2,$T3>::__base::__node_pointer)this) |
| ->__value_ |
| </ValueNode> |
| </TreeItems> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::priority_queue<*>"> |
| <DisplayString>{c}</DisplayString> |
| <Expand> |
| <ExpandedItem>c</ExpandedItem> |
| <Item Name="[comp]">comp</Item> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::set<*>"> |
| <Intrinsic Name="size" Expression="*(size_type*)&__tree_.__pair3_" /> |
| <DisplayString>{{ size={size()} }}</DisplayString> |
| <Expand> |
| <Item Name="[size]">size()</Item> |
| <TreeItems> |
| <Size>size()</Size> |
| <HeadPointer> |
| ((__base::__node_pointer)&__tree_.__pair1_)->__left_ |
| </HeadPointer> |
| <LeftPointer> |
| ((std::__1::set<$T1,$T2,$T3>::__base::__node_pointer)this) |
| ->__left_ |
| </LeftPointer> |
| <RightPointer> |
| ((std::__1::set<$T1,$T2,$T3>::__base::__node_pointer)this) |
| ->__right_ |
| </RightPointer> |
| <ValueNode> |
| ((std::__1::set<$T1,$T2,$T3>::__base::__node_pointer)this) |
| ->__value_ |
| </ValueNode> |
| </TreeItems> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::stack<*>"> |
| <AlternativeType Name="std::__1::queue<*>" /> |
| <DisplayString>{c}</DisplayString> |
| <Expand> |
| <ExpandedItem>c</ExpandedItem> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::__tuple_leaf<*,*,0>"> |
| <DisplayString>{__value_}</DisplayString> |
| </Type> |
| |
| <Type Name="std::__1::tuple<>"> |
| <DisplayString>()</DisplayString> |
| </Type> |
| |
| <Type Name="std::__1::tuple<*>"> |
| <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_})</DisplayString> |
| <Expand> |
| <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::tuple<*,*>"> |
| <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_})</DisplayString> |
| <Expand> |
| <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> |
| <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::tuple<*,*,*>"> |
| <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_})</DisplayString> |
| <Expand> |
| <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> |
| <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> |
| <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::tuple<*,*,*,*>"> |
| <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_})</DisplayString> |
| <Expand> |
| <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> |
| <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> |
| <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> |
| <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::tuple<*,*,*,*,*>"> |
| <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_}, {(std::__1::__tuple_leaf<4,$T5,0>)__base_})</DisplayString> |
| <Expand> |
| <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> |
| <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> |
| <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> |
| <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> |
| <Item Name="[4]">(std::__1::__tuple_leaf<4,$T5,0>)__base_</Item> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::tuple<*,*,*,*,*,*>"> |
| <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_}, {(std::__1::__tuple_leaf<4,$T5,0>)__base_}, {(std::__1::__tuple_leaf<5,$T6,0>)__base_})</DisplayString> |
| <Expand> |
| <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> |
| <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> |
| <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> |
| <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> |
| <Item Name="[4]">(std::__1::__tuple_leaf<4,$T5,0>)__base_</Item> |
| <Item Name="[5]">(std::__1::__tuple_leaf<5,$T6,0>)__base_</Item> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::tuple<*,*,*,*,*,*,*>"> |
| <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_}, {(std::__1::__tuple_leaf<4,$T5,0>)__base_}, {(std::__1::__tuple_leaf<5,$T6,0>)__base_}, {(std::__1::__tuple_leaf<6,$T7,0>)__base_})</DisplayString> |
| <Expand> |
| <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> |
| <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> |
| <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> |
| <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> |
| <Item Name="[4]">(std::__1::__tuple_leaf<4,$T5,0>)__base_</Item> |
| <Item Name="[5]">(std::__1::__tuple_leaf<5,$T6,0>)__base_</Item> |
| <Item Name="[6]">(std::__1::__tuple_leaf<6,$T7,0>)__base_</Item> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::unique_ptr<*>"> |
| <Intrinsic Name="value" Expression="*($T1**)&__ptr_" /> |
| <SmartPointer Usage="Minimal">value()</SmartPointer> |
| <DisplayString Condition="value() == 0">empty</DisplayString> |
| <DisplayString Condition="value() != 0"> |
| unique_ptr {value()}</DisplayString> |
| <Expand> |
| <Item Condition="value() != 0" Name="[ptr]">value()</Item> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::unordered_map<*>"> |
| <AlternativeType Name="std::__1::unordered_multimap<*>" /> |
| <AlternativeType Name="std::__1::unordered_multiset<*>" /> |
| <AlternativeType Name="std::__1::unordered_set<*>" /> |
| <Intrinsic Name="size" Expression="*(size_type*)&__table_.__p2_" /> |
| <Intrinsic Name="bucket_count" |
| Expression="*(size_type*)& |
| ((__table::__bucket_list_deleter*) |
| ((void**)&__table_.__bucket_list_ + 1)) |
| ->__data_" /> |
| <DisplayString>{{ size={size()} }}</DisplayString> |
| <Expand> |
| <Item Name="[bucket_count]">bucket_count()</Item> |
| <Item Name="[load_factor]"> |
| bucket_count() != 0 ? (float)size() / bucket_count() : 0.f</Item> |
| <Item Name="[max_load_factor]">*(float*)&__table_.__p3_</Item> |
| <!-- Use CustomListItems instead of LinkedListItems because we |
| need to cast to __table::__node_pointer and LinkedListItems |
| evaluates <Value> in the context of the node, not of the container, |
| so we'd have to say std::unordered_map<$T1,...>::__table::__node_pointer |
| and then we couldn't share this <Type> between unordered_(multi)map |
| and unordered_(multi)set. --> |
| <CustomListItems> |
| <Variable Name="node" |
| InitialValue="*(__table::__next_pointer*)&__table_.__p1_" /> |
| <Size>size()</Size> |
| <Loop> |
| <Item>(*(__table::__node_pointer*)&node)->__value_</Item> |
| <Exec>node = node->__next_</Exec> |
| </Loop> |
| </CustomListItems> |
| </Expand> |
| </Type> |
| <!-- This is the node __value_ of an unordered_(multi)map. Expand it through |
| a separate formatter instead of in the <Item> expression above so that the |
| same <Type> works for unordered_(multi)set and unordered_(multi)map. --> |
| <Type Name="std::__1::__hash_value_type<*>"> |
| <DisplayString>{__cc}</DisplayString> |
| <Expand> |
| <ExpandedItem>__cc</ExpandedItem> |
| </Expand> |
| </Type> |
| |
| <Type Name="std::__1::vector<*>"> |
| <Intrinsic Name="size" Expression="__end_ - __begin_" /> |
| <DisplayString>{{ size={size()} }}</DisplayString> |
| <Expand> |
| <ArrayItems> |
| <Size>size()</Size> |
| <ValuePointer>__begin_</ValuePointer> |
| </ArrayItems> |
| </Expand> |
| </Type> |
| </AutoVisualizer> |