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.
|
||||
# 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 utils import DisplayFormat
|
||||
from dumper import Children, DumperBase
|
||||
@@ -53,24 +76,10 @@ def qdump__std____1__list(d, value):
|
||||
|
||||
|
||||
def qdump__std____1__set(d, value):
|
||||
# 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
|
||||
# see disclaimer #1
|
||||
alloc_type = value.type[2]
|
||||
alloc_size = alloc_type.size()
|
||||
# size of empty allocators (which are the majority) is reported as 1
|
||||
# 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
|
||||
# see disclaimer #2
|
||||
if alloc_size > 1:
|
||||
(proxy, head, alloc, size) = value.split(f'pp{{{alloc_type.name}}}p')
|
||||
else:
|
||||
@@ -109,30 +118,30 @@ def qform__std____1__map():
|
||||
|
||||
|
||||
def qdump__std____1__map(d, value):
|
||||
try:
|
||||
(proxy, head, size) = value.split("ppp")
|
||||
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
||||
alloc_type = value.type[3] # see disclaimer #1
|
||||
alloc_size = alloc_type.size()
|
||||
# see disclaimers #2 and #3
|
||||
if alloc_size > 1:
|
||||
(begin_node_ptr, head, alloc, size) = value.split(f'pp{{{alloc_type.name}}}p')
|
||||
else:
|
||||
(begin_node_ptr, head, size) = value.split("ppp")
|
||||
|
||||
# Sometimes there is extra data at the front. Don't know why at the moment.
|
||||
except RuntimeError:
|
||||
(junk, proxy, head, size) = value.split("pppp")
|
||||
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
||||
|
||||
d.putItemCount(size)
|
||||
|
||||
if d.isExpanded():
|
||||
keyType = value.type[0]
|
||||
valueType = value.type[1]
|
||||
pairType = value.type[3][0]
|
||||
valType = value.type[1]
|
||||
|
||||
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:
|
||||
for res in in_order_traversal(left):
|
||||
yield res
|
||||
|
||||
yield pair.split("{%s}@{%s}" % (keyType.name, valueType.name))[::2]
|
||||
yield key, val
|
||||
|
||||
if right:
|
||||
for res in in_order_traversal(right):
|
||||
|
@@ -8693,6 +8693,7 @@ void tst_Dumpers::dumper_data()
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory_resource>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@@ -8731,16 +8732,17 @@ void tst_Dumpers::dumper_data()
|
||||
us.insert(i);
|
||||
ums.insert(i);
|
||||
|
||||
m.emplace(i, i);
|
||||
mm.emplace(i, i);
|
||||
um.emplace(i, i);
|
||||
umm.emplace(i, i);
|
||||
m.emplace(i, count + i);
|
||||
mm.emplace(i, count + i);
|
||||
um.emplace(i, count + i);
|
||||
umm.emplace(i, count + i);
|
||||
|
||||
v.push_back(i);
|
||||
}
|
||||
)",
|
||||
"&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"} % GdbEngine
|
||||
+ 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{"ums", "<10 items>", "std::pmr::unordered_multiset<int>"} % NoGdbEngine
|
||||
+ 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.5", "[5] 5", "5", ""}
|
||||
+ Check{"mm", "<10 items>", "std::pmr::multimap<int, int>"} % NoGdbEngine
|
||||
+ Check{"m.5", "[5] 5", "15", ""} % NoLldbEngine
|
||||
+ Check{"mm", "<10 items>", "std::pmr::multimap<int, int>"} % CdbEngine
|
||||
+ 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"} % GdbEngine
|
||||
+ Check{"umm", "<10 items>", "std::pmr::unordered_multimap<int, int>"} % NoGdbEngine
|
||||
|
Reference in New Issue
Block a user