Fix STL container dumpers with _GLIBCXX_DEBUG

Fixed behavior of the libstdc++ dumpers for the following types
with `_GLIBCXX_DEBUG` macro enabled:
  * `std::deque`
  * `std::list`
  * `std::multimap`
  * `std::multiset`

Fixed libc++ dumpers for the following types:
  * `std::unordered_map`
  * `std::unordered_multimap`
  * `std::unordered_multiset`
  * `std::unordered_set`

Added a dumper for `std::forward_list`.

Fixes: QTCREATORBUG-20476
Change-Id: I802b0eaf31cdea77d980ca18d4c3fae15a86a3d4
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Andrii Semkiv
2024-09-30 18:10:17 +02:00
parent 2b6f9b4415
commit fca70aa959
3 changed files with 112 additions and 11 deletions

View File

@@ -1,7 +1,7 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
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
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
@@ -23,6 +23,10 @@ def qdump__std____1__deque(d, value):
qdumpHelper__std__deque__libcxx(d, value)
def qdump__std____1__forward_list(d, value):
qdump__std__forward_list(d, value)
def qdump__std____1__list(d, value):
if value.type.size() == 3 * d.ptrSize():
# C++11 only.
@@ -308,7 +312,7 @@ def qform__std____1__unordered_map():
def qdump__std____1__unordered_map(d, value):
(size, _) = value["__table_"]["__p2_"].split("pp")
size = value["__table_"]["__p2_"]["__value_"].integer()
d.putItemCount(size)
keyType = value.type[0]
@@ -316,7 +320,7 @@ def qdump__std____1__unordered_map(d, value):
pairType = value.type[4][0]
if d.isExpanded():
curr = value["__table_"]["__p1_"].split("pp")[0]
curr = value["__table_"]["__p1_"].split("p")[0]
def traverse_list(node):
while node:
@@ -329,14 +333,18 @@ def qdump__std____1__unordered_map(d, value):
d.putPairItem(i, value, 'key', 'value')
def qdump__std____1__unordered_multimap(d, value):
qdump__std____1__unordered_map(d, value)
def qdump__std____1__unordered_set(d, value):
(size, _) = value["__table_"]["__p2_"].split("pp")
size = value["__table_"]["__p2_"]["__value_"].integer()
d.putItemCount(size)
valueType = value.type[0]
if d.isExpanded():
curr = value["__table_"]["__p1_"].split("pp")[0]
curr = value["__table_"]["__p1_"].split("p")[0]
def traverse_list(node):
while node:

View File

@@ -62,8 +62,14 @@ def qdumpHelper__std__deque__libstdcxx(d, value):
innerSize = innerType.size()
bufsize = 512 // innerSize if innerSize < 512 else 1
(mapptr, mapsize, startCur, startFirst, startLast, startNode,
finishCur, finishFirst, finishLast, finishNode) = value.split("pppppppppp")
start = value['_M_start']
startCur = start['_M_cur'].pointer()
startLast = start['_M_last'].pointer()
startNode = start['_M_node'].pointer()
finish = value['_M_finish']
finishCur = finish['_M_cur'].pointer()
finishFirst = finish['_M_first'].pointer()
finishNode = finish['_M_node'].pointer()
size = bufsize * ((finishNode - startNode) // d.ptrSize() - 1)
size += (finishCur - finishFirst) // innerSize
@@ -178,9 +184,16 @@ def qdump__std__list(d, value):
qdump__std__list__QNX(d, value)
return
if value.type.size() == 3 * d.ptrSize():
# QTCREATORBUG-20476: GCC with _GLIBCXX_DEBUG prepends the head node
# with some debug information
if value.hasMember('_M_impl'):
sentinel = value['_M_impl']['_M_node']
else:
sentinel = value
if sentinel.type.size() == 3 * d.ptrSize():
# C++11 only.
(dummy1, dummy2, size) = value.split("ppp")
(dummy1, dummy2, size) = sentinel.split("ppp")
d.putItemCount(size)
else:
# Need to count manually.
@@ -193,7 +206,7 @@ def qdump__std__list(d, value):
d.putItemCount(size, 1000)
if d.isExpanded():
p = d.extractPointer(value)
p = d.extractPointer(sentinel)
innerType = value.type[0]
with Children(d, size, maxNumChild=1000, childType=innerType):
for i in d.childRange():
@@ -232,6 +245,43 @@ def qdump__std____cxx11__list(d, value):
qdump__std__list(d, value)
def qdump__std__forward_list(d, value):
# QTCREATORBUG-20476: GCC with _GLIBCXX_DEBUG prepends the head node
# with some debug information
if value.hasMember('_M_impl'):
head = value['_M_impl']['_M_head']
# MSVC stores the head in a compressed pair with the allocator
# (which is normally an empty class)
elif value.hasMember('_Mypair'):
head = value['_Mypair']['_Myval2']['_Myhead']
else:
head = value
# Need to count manually.
p = d.extractPointer(head)
size = 0
while p and size < 1001:
size += 1
p = d.extractPointer(p)
d.putItemCount(size, 1000)
if d.isExpanded():
p = d.extractPointer(head)
innerType = value.type[0]
with Children(d, size, maxNumChild=1000, childType=innerType):
for i in d.childRange():
d.putSubItem(i, d.createValue(p + d.ptrSize(), innerType))
p = d.extractPointer(p)
def qdump__std____debug__forward_list(d, value):
qdump__std__forward_list(d, value)
def qdump__std____cxx11__forward_list(d, value):
qdump__std__forward_list(d, value)
def qform__std__map():
return [DisplayFormat.CompactMap]
@@ -242,7 +292,7 @@ def qdump__std__map(d, value):
return
# stuff is actually (color, pad) with 'I@', but we can save cycles/
(compare, stuff, parent, left, right) = value.split('ppppp')
parent = value["_M_t"]["_M_impl"]["_M_header"]
size = value["_M_t"]["_M_impl"]["_M_node_count"].integer()
d.check(0 <= size and size <= 100 * 1000 * 1000)
d.putItemCount(size)
@@ -321,6 +371,14 @@ def qdump__std__multiset(d, value):
qdump__std__set(d, value)
def qdump__std____debug__multiset(d, value):
qdump__std__multiset(d, value)
def qdump__std____cxx1998__multiset(d, value):
qdump__std__multiset(d, value)
def qdump__std____cxx1998__map(d, value):
qdump__std__map(d, value)
@@ -333,6 +391,14 @@ def qdump__std__multimap(d, value):
return qdump__std__map(d, value)
def qdump__std____debug__multimap(d, value):
qdump__std__multimap(d, value)
def qdump__std____cxx1998__multimap(d, value):
qdump__std__multimap(d, value)
def qdumpHelper__std__tree__iterator(d, value, isSet=False):
treeTypeName = None
if value.type.name.endswith("::iterator"):

View File

@@ -4905,6 +4905,33 @@ void tst_Dumpers::dumper_data()
+ Check("l4.@1.1", "[1]", "2", "int");
QTest::newRow("StdForwardList")
<< Data("#include <forward_list>\n",
"std::forward_list<int> fl0;\n"
"std::forward_list<int> fl1;\n"
"for (int i = 0; i < 10000; ++i)\n"
" fl1.push_front(i);\n"
"std::forward_list<bool> fl2 = {true, false};\n",
"&fl0, &fl1, &fl2")
+ BigArrayProfile()
+ Check("fl0", "<0 items>", "std::forward_list<int>")
+ Check("fl1", ValuePattern("<.*1000.* items>"), "std::forward_list<int>")
+ Check("fl1.0", "[0]", "9999", "int")
+ Check("fl1.1", "[1]", "9998", "int")
+ Check("fl1.999", "[999]", "9000", "int")
+ Check("fl2", "<2 items>", "std::forward_list<bool>")
+ Check("fl2.0", "[0]", "1", "bool")
+ Check("fl2.1", "[1]", "0", "bool");
QTest::newRow("StdListQt")
<< Data("#include <list>\n" + fooData,