Debugger: Prepend '*'s for autodereferenced pointers

If automatic dereferencing of pointers is enabled, the
"Value" and "Type" columns for pointers hold the values for
the dereferenced pointers.

In order to have a consistent behavior for the "Name" column
as well, prepend '*'s to indicate that the variable/expression
has actually been dereferenced.
Add parantheses around the original expression if it doesn't
match a simple regex for variable names, to avoid that the
leading '*' changes the meaning of the expression
(so e.g. a dereferenced 'somepointer + 1' is displayed
as  '*(somepointer + 1)' rather than '*somepointer + 1').

This introduces a new 'autoderefcount' field to propagate the
information how many levels of dereferencing have taken
place from the Python to the C++ side, which is then
used to add the leading '*'s for the display name.

Fixes: QTCREATORBUG-20907
Change-Id: Ia9a41cb42e25ba72a6d980a765dbe2b454deb8c8
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Michael Weghorn
2021-02-17 08:40:48 +01:00
parent c6493e170f
commit f4dc3fd5c5
4 changed files with 29 additions and 0 deletions

View File

@@ -1312,6 +1312,11 @@ class DumperBase():
savedCurrentChildType = self.currentChildType savedCurrentChildType = self.currentChildType
self.currentChildType = innerType.name self.currentChildType = innerType.name
derefValue.name = '*' derefValue.name = '*'
derefValue.autoDerefCount = value.autoDerefCount + 1
if derefValue.type.code != TypeCode.Pointer:
self.putField('autoderefcount', '{}'.format(derefValue.autoDerefCount))
self.putItem(derefValue) self.putItem(derefValue)
self.currentChildType = savedCurrentChildType self.currentChildType = savedCurrentChildType
@@ -2920,6 +2925,7 @@ class DumperBase():
self.targetValue = None # For references. self.targetValue = None # For references.
self.isBaseClass = None self.isBaseClass = None
self.nativeValue = None self.nativeValue = None
self.autoDerefCount = 0
def copy(self): def copy(self):
val = self.dumper.Value(self.dumper) val = self.dumper.Value(self.dumper)

View File

@@ -115,6 +115,7 @@ WatchItem::WatchItem() :
wantsChildren(false), wantsChildren(false),
valueEnabled(true), valueEnabled(true),
valueEditable(true), valueEditable(true),
autoDerefCount(0),
outdated(false) outdated(false)
{ {
} }
@@ -388,6 +389,14 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
else if (mi.data() == "false") else if (mi.data() == "false")
valueEditable = false; valueEditable = false;
mi = input["autoderefcount"];
if (mi.isValid()) {
bool ok = false;
uint derefCount = mi.data().toUInt(&ok);
if (ok)
autoDerefCount = derefCount;
}
mi = input["numchild"]; // GDB/MI mi = input["numchild"]; // GDB/MI
if (mi.isValid()) if (mi.isValid())
setHasChildren(mi.toInt() > 0); setHasChildren(mi.toInt() > 0);

View File

@@ -99,6 +99,7 @@ public:
bool wantsChildren; bool wantsChildren;
bool valueEnabled; // Value will be enabled or not bool valueEnabled; // Value will be enabled or not
bool valueEditable; // Value will be editable bool valueEditable; // Value will be editable
uint autoDerefCount; // number of levels of automatic dereferencing that has taken place (for pointer types)
bool outdated; // \internal item is to be removed. bool outdated; // \internal item is to be removed.
double time = 0; // Time used on the dumper side to produce this item double time = 0; // Time used on the dumper side to produce this item

View File

@@ -869,6 +869,19 @@ static QString displayName(const WatchItem *item)
else else
result = watchModel(item)->removeNamespaces(item->name); result = watchModel(item)->removeNamespaces(item->name);
// prepend '*'s to indicate where autodereferencing has taken place
if (item->autoDerefCount > 0) {
// add parentheses for everything except simple variable names (e.g. pointer arithmetics,...)
QRegularExpression variableNameRegex("^[a-zA-Z0-9_]+$");
bool addParanthesis = !variableNameRegex.match(result).hasMatch();
if (addParanthesis)
result = "(" + result;
for (uint i = 0; i < item->autoDerefCount; i++)
result = "*" + result;
if (addParanthesis)
result += ")";
}
// Simplify names that refer to base classes. // Simplify names that refer to base classes.
if (result.startsWith('[')) { if (result.startsWith('[')) {
result = simplifyType(result); result = simplifyType(result);