forked from qt-creator/qt-creator
Debugger: fix pmr containers test
The initial version of the pmr containers dumper test
had a couple of shortcomings:
* there was an inclusion of `<memory_resource>` missing
in the test program body
* some test setups use compilers that do not use C++17 by default
so the correct profile must be specified for the test
Disabled a bunch of checks that did not work with libcxx
due to incorrect reported size of
`std::pmr::polymorphic_allocator<std::pair<const int, int>>`.
Fixed the libcxx dumper for `std::map` (the ordinary, non-pmr, one).
As turned out, it was broken due to an incorrect padding calculation
for `std::pair<const int, int>`.
This has been worked around by using pair's inner types explicitly.
Amends: cb23332ae5
Task number: QTCREATORBUG-30224
Change-Id: I937295f88083ee9521a35ac7dbe22303ef52bd53
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -1,6 +1,29 @@
|
|||||||
# Copyright (C) 2022 The Qt Company Ltd.
|
# Copyright (C) 2022 The Qt Company Ltd.
|
||||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
# Disclaimers:
|
||||||
|
# 1. Looking up the allocator template type is potentially an expensive operation.
|
||||||
|
# A better alternative would be finding out the allocator type
|
||||||
|
# through accessing a class member.
|
||||||
|
# However due to different implementations doing things very differently
|
||||||
|
# it is deemed acceptable.
|
||||||
|
# Specifically:
|
||||||
|
# * GCC's `_Rb_tree_impl` basically inherits from the allocator, the comparator
|
||||||
|
# and the sentinel node
|
||||||
|
# * Clang packs the allocator and the sentinel node into a compressed pair,
|
||||||
|
# so depending on whether the allocator is sized or not,
|
||||||
|
# there may or may not be a member to access
|
||||||
|
# * MSVC goes even one step further and stores the allocator and the sentinel node together
|
||||||
|
# in a compressed pair, which in turn is stored together with the comparator inside
|
||||||
|
# another compressed pair
|
||||||
|
# 2. `size` on an empty type, which the majority of the allocators are of,
|
||||||
|
# for whatever reason reports 1. In theory there can be allocators whose type is truly 1 byte,
|
||||||
|
# in which case we will have issues, but in practice they should be rather rare.
|
||||||
|
# 3. Note that sometimes the size of `std::pmr::polymorphic_allocator` is bizarrely reported
|
||||||
|
# as exactly 0, for example this happens with
|
||||||
|
# `std::__1::pmr::polymorphic_allocator<std::__1::pair<const int, int>>` from `std::pmr::map`,
|
||||||
|
# so dumping pmr containers still may still have some breakages for libcxx
|
||||||
|
|
||||||
from stdtypes import qdump__std__array, qdump__std__complex, qdump__std__once_flag, qdump__std__unique_ptr, qdumpHelper__std__deque__libcxx, qdumpHelper__std__vector__libcxx, qdump__std__forward_list
|
from stdtypes import qdump__std__array, qdump__std__complex, qdump__std__once_flag, qdump__std__unique_ptr, qdumpHelper__std__deque__libcxx, qdumpHelper__std__vector__libcxx, qdump__std__forward_list
|
||||||
from utils import DisplayFormat
|
from utils import DisplayFormat
|
||||||
from dumper import Children, DumperBase
|
from dumper import Children, DumperBase
|
||||||
@@ -53,24 +76,10 @@ def qdump__std____1__list(d, value):
|
|||||||
|
|
||||||
|
|
||||||
def qdump__std____1__set(d, value):
|
def qdump__std____1__set(d, value):
|
||||||
# Looking up the allocator template type is potentially an expensive operation.
|
# see disclaimer #1
|
||||||
# A better alternative would be finding out the allocator type through accessing a class member.
|
|
||||||
# However due to different implementations doing things very differently
|
|
||||||
# it is deemed acceptable.
|
|
||||||
# Specifically:
|
|
||||||
# * GCC's `_Rb_tree_impl` basically inherits from the allocator, the comparator
|
|
||||||
# and the sentinel node
|
|
||||||
# * Clang packs the allocator and the sentinel node into a compressed pair,
|
|
||||||
# so depending on whether the allocator is sized or not,
|
|
||||||
# there may or may not be a member to access
|
|
||||||
# * MSVC goes even one step further and stores the allocator and the sentinel node together
|
|
||||||
# in a compressed pair, which in turn is stored together with the comparator inside
|
|
||||||
# another compressed pair
|
|
||||||
alloc_type = value.type[2]
|
alloc_type = value.type[2]
|
||||||
alloc_size = alloc_type.size()
|
alloc_size = alloc_type.size()
|
||||||
# size of empty allocators (which are the majority) is reported as 1
|
# see disclaimer #2
|
||||||
# in theory there can be allocators whose size is truly 1 byte,
|
|
||||||
# in which case this will cause issues, but in practice they should be rather rare
|
|
||||||
if alloc_size > 1:
|
if alloc_size > 1:
|
||||||
(proxy, head, alloc, size) = value.split(f'pp{{{alloc_type.name}}}p')
|
(proxy, head, alloc, size) = value.split(f'pp{{{alloc_type.name}}}p')
|
||||||
else:
|
else:
|
||||||
@@ -109,30 +118,30 @@ def qform__std____1__map():
|
|||||||
|
|
||||||
|
|
||||||
def qdump__std____1__map(d, value):
|
def qdump__std____1__map(d, value):
|
||||||
try:
|
alloc_type = value.type[3] # see disclaimer #1
|
||||||
(proxy, head, size) = value.split("ppp")
|
alloc_size = alloc_type.size()
|
||||||
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
# see disclaimers #2 and #3
|
||||||
|
if alloc_size > 1:
|
||||||
# Sometimes there is extra data at the front. Don't know why at the moment.
|
(begin_node_ptr, head, alloc, size) = value.split(f'pp{{{alloc_type.name}}}p')
|
||||||
except RuntimeError:
|
else:
|
||||||
(junk, proxy, head, size) = value.split("pppp")
|
(begin_node_ptr, head, size) = value.split("ppp")
|
||||||
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
|
||||||
|
|
||||||
|
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
||||||
d.putItemCount(size)
|
d.putItemCount(size)
|
||||||
|
|
||||||
if d.isExpanded():
|
if d.isExpanded():
|
||||||
keyType = value.type[0]
|
keyType = value.type[0]
|
||||||
valueType = value.type[1]
|
valType = value.type[1]
|
||||||
pairType = value.type[3][0]
|
|
||||||
|
|
||||||
def in_order_traversal(node):
|
def in_order_traversal(node):
|
||||||
(left, right, parent, color, pad, pair) = d.split("pppB@{%s}" % (pairType.name), node)
|
(left, right, parent, color, _pad_1, key, _pad_2, val) = d.split(
|
||||||
|
f'pppB@{{{keyType.name}}}@{{{valType.name}}}', node)
|
||||||
|
|
||||||
if left:
|
if left:
|
||||||
for res in in_order_traversal(left):
|
for res in in_order_traversal(left):
|
||||||
yield res
|
yield res
|
||||||
|
|
||||||
yield pair.split("{%s}@{%s}" % (keyType.name, valueType.name))[::2]
|
yield key, val
|
||||||
|
|
||||||
if right:
|
if right:
|
||||||
for res in in_order_traversal(right):
|
for res in in_order_traversal(right):
|
||||||
|
@@ -8693,6 +8693,7 @@ void tst_Dumpers::dumper_data()
|
|||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory_resource>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
@@ -8731,16 +8732,17 @@ void tst_Dumpers::dumper_data()
|
|||||||
us.insert(i);
|
us.insert(i);
|
||||||
ums.insert(i);
|
ums.insert(i);
|
||||||
|
|
||||||
m.emplace(i, i);
|
m.emplace(i, count + i);
|
||||||
mm.emplace(i, i);
|
mm.emplace(i, count + i);
|
||||||
um.emplace(i, i);
|
um.emplace(i, count + i);
|
||||||
umm.emplace(i, i);
|
umm.emplace(i, count + i);
|
||||||
|
|
||||||
v.push_back(i);
|
v.push_back(i);
|
||||||
}
|
}
|
||||||
)",
|
)",
|
||||||
"&d, &fl, &l, &s, &ms, &us, &ums, &m, &mm, &um, &umm, &v"
|
"&d, &fl, &l, &s, &ms, &us, &ums, &m, &mm, &um, &umm, &v"
|
||||||
}
|
}
|
||||||
|
+ Cxx17Profile{}
|
||||||
+ Check{"d", "<10 items>", "std::pmr::deque<int>"} % NoGdbEngine
|
+ Check{"d", "<10 items>", "std::pmr::deque<int>"} % NoGdbEngine
|
||||||
+ Check{"d", "<10 items>", "std::pmr::deque"} % GdbEngine
|
+ Check{"d", "<10 items>", "std::pmr::deque"} % GdbEngine
|
||||||
+ Check{"d.1", "[1]", "8", "int"}
|
+ Check{"d.1", "[1]", "8", "int"}
|
||||||
@@ -8760,12 +8762,18 @@ void tst_Dumpers::dumper_data()
|
|||||||
+ Check{"us", "<10 items>", "std::pmr::unordered_set"} % GdbEngine
|
+ Check{"us", "<10 items>", "std::pmr::unordered_set"} % GdbEngine
|
||||||
+ Check{"ums", "<10 items>", "std::pmr::unordered_multiset<int>"} % NoGdbEngine
|
+ Check{"ums", "<10 items>", "std::pmr::unordered_multiset<int>"} % NoGdbEngine
|
||||||
+ Check{"ums", "<10 items>", "std::pmr::unordered_multiset"} % GdbEngine
|
+ Check{"ums", "<10 items>", "std::pmr::unordered_multiset"} % GdbEngine
|
||||||
+ Check{"m", "<10 items>", "std::pmr::map<int, int>"} % NoGdbEngine
|
|
||||||
|
// There is a bizzare interaction of `DumperBase.Type.size` (see Python scripts) and libcxx
|
||||||
|
// that results in the size of
|
||||||
|
// `std::__1::pmr::polymorphic_allocator<std::__1::pair<const int, int>>`
|
||||||
|
// from `std::pmr::map` being reported as exactly 0 which breaks dumping
|
||||||
|
+ Check{"m", "<10 items>", "std::pmr::map<int, int>"} % CdbEngine
|
||||||
+ Check{"m", "<10 items>", "std::pmr::map"} % GdbEngine
|
+ Check{"m", "<10 items>", "std::pmr::map"} % GdbEngine
|
||||||
+ Check{"m.5", "[5] 5", "5", ""}
|
+ Check{"m.5", "[5] 5", "15", ""} % NoLldbEngine
|
||||||
+ Check{"mm", "<10 items>", "std::pmr::multimap<int, int>"} % NoGdbEngine
|
+ Check{"mm", "<10 items>", "std::pmr::multimap<int, int>"} % CdbEngine
|
||||||
+ Check{"mm", "<10 items>", "std::pmr::multimap"} % GdbEngine
|
+ Check{"mm", "<10 items>", "std::pmr::multimap"} % GdbEngine
|
||||||
+ Check{"mm.5", "[5] 5", "5", ""}
|
+ Check{"mm.5", "[5] 5", "15", ""} % NoLldbEngine
|
||||||
|
|
||||||
+ Check{"um", "<10 items>", "std::pmr::unordered_map<int, int>"} % NoGdbEngine
|
+ Check{"um", "<10 items>", "std::pmr::unordered_map<int, int>"} % NoGdbEngine
|
||||||
+ Check{"um", "<10 items>", "std::pmr::unordered_map"} % GdbEngine
|
+ Check{"um", "<10 items>", "std::pmr::unordered_map"} % GdbEngine
|
||||||
+ Check{"umm", "<10 items>", "std::pmr::unordered_multimap<int, int>"} % NoGdbEngine
|
+ Check{"umm", "<10 items>", "std::pmr::unordered_multimap<int, int>"} % NoGdbEngine
|
||||||
|
Reference in New Issue
Block a user