forked from qt-creator/qt-creator
Debugger: Remove old formatting hacks
These go back to the time where we faced raw GDB output. Nowadays we get polished data from the dumpers already. Change-Id: Ifeb2c0609d482bbd6d7783242f13c74ecc320233 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -40,11 +40,6 @@ bool isPointerType(const QString &type)
|
|||||||
return type.endsWith('*') || type.endsWith("* const");
|
return type.endsWith('*') || type.endsWith("* const");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCharPointerType(const QString &type)
|
|
||||||
{
|
|
||||||
return type == "char *" || type == "const char *" || type == "char const *";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isIntType(const QString &type)
|
bool isIntType(const QString &type)
|
||||||
{
|
{
|
||||||
if (type.isEmpty())
|
if (type.isEmpty())
|
||||||
@@ -128,8 +123,7 @@ bool WatchItem::isVTablePointer() const
|
|||||||
{
|
{
|
||||||
// First case: Cdb only. No user type can be named like this, this is safe.
|
// First case: Cdb only. No user type can be named like this, this is safe.
|
||||||
// Second case: Python dumper only.
|
// Second case: Python dumper only.
|
||||||
return type.startsWith("__fptr()")
|
return type.startsWith("__fptr()") || (type.isEmpty() && name == "[vptr]");
|
||||||
|| (type.isEmpty() && name == QLatin1String("[vptr]"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchItem::setError(const QString &msg)
|
void WatchItem::setError(const QString &msg)
|
||||||
@@ -147,87 +141,6 @@ void WatchItem::setValue(const QString &value0)
|
|||||||
value.clear();
|
value.clear();
|
||||||
wantsChildren = true; // at least one...
|
wantsChildren = true; // at least one...
|
||||||
}
|
}
|
||||||
// strip off quoted characters for chars.
|
|
||||||
if (value.endsWith(QLatin1Char('\'')) && type.endsWith("char")) {
|
|
||||||
const int blankPos = value.indexOf(QLatin1Char(' '));
|
|
||||||
if (blankPos != -1)
|
|
||||||
value.truncate(blankPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// avoid duplicated information
|
|
||||||
if (value.startsWith(QLatin1Char('(')) && value.contains(QLatin1String(") 0x")))
|
|
||||||
value.remove(0, value.lastIndexOf(QLatin1String(") 0x")) + 2);
|
|
||||||
|
|
||||||
// doubles are sometimes displayed as "@0x6141378: 1.2".
|
|
||||||
// I don't want that.
|
|
||||||
if (/*isIntOrFloatType(type) && */ value.startsWith(QLatin1String("@0x"))
|
|
||||||
&& value.contains(QLatin1Char(':'))) {
|
|
||||||
value.remove(0, value.indexOf(QLatin1Char(':')) + 2);
|
|
||||||
setHasChildren(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// "numchild" is sometimes lying
|
|
||||||
//MODEL_DEBUG("\n\n\nPOINTER: " << type << value);
|
|
||||||
if (isPointerType(type))
|
|
||||||
setHasChildren(value != QLatin1String("0x0") && value != QLatin1String("<null>")
|
|
||||||
&& !isCharPointerType(type));
|
|
||||||
|
|
||||||
// pointer type information is available in the 'type'
|
|
||||||
// column. No need to duplicate it here.
|
|
||||||
if (value.startsWith('(' + type + ") 0x"))
|
|
||||||
value = value.section(QLatin1Char(' '), -1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GuessChildrenResult { HasChildren, HasNoChildren, HasPossiblyChildren };
|
|
||||||
|
|
||||||
static GuessChildrenResult guessChildren(const QString &type)
|
|
||||||
{
|
|
||||||
if (isIntOrFloatType(type))
|
|
||||||
return HasNoChildren;
|
|
||||||
if (isCharPointerType(type))
|
|
||||||
return HasNoChildren;
|
|
||||||
if (isPointerType(type))
|
|
||||||
return HasChildren;
|
|
||||||
if (type.endsWith("QString"))
|
|
||||||
return HasNoChildren;
|
|
||||||
return HasPossiblyChildren;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WatchItem::setType(const QString &str, bool guessChildrenFromType)
|
|
||||||
{
|
|
||||||
type = str.trimmed();
|
|
||||||
bool changed = true;
|
|
||||||
while (changed) {
|
|
||||||
if (type.endsWith("const"))
|
|
||||||
type.chop(5);
|
|
||||||
else if (type.endsWith(' '))
|
|
||||||
type.chop(1);
|
|
||||||
else if (type.startsWith("const "))
|
|
||||||
type = type.mid(6);
|
|
||||||
else if (type.startsWith("volatile "))
|
|
||||||
type = type.mid(9);
|
|
||||||
else if (type.startsWith("class "))
|
|
||||||
type = type.mid(6);
|
|
||||||
else if (type.startsWith("struct "))
|
|
||||||
type = type.mid(7);
|
|
||||||
else if (type.startsWith(' '))
|
|
||||||
type = type.mid(1);
|
|
||||||
else
|
|
||||||
changed = false;
|
|
||||||
}
|
|
||||||
if (guessChildrenFromType) {
|
|
||||||
switch (guessChildren(type)) {
|
|
||||||
case HasChildren:
|
|
||||||
setHasChildren(true);
|
|
||||||
break;
|
|
||||||
case HasNoChildren:
|
|
||||||
setHasChildren(false);
|
|
||||||
break;
|
|
||||||
case HasPossiblyChildren:
|
|
||||||
setHasChildren(true); // FIXME: bold assumption
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString WatchItem::toString() const
|
QString WatchItem::toString() const
|
||||||
@@ -397,7 +310,7 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
|
|||||||
{
|
{
|
||||||
GdbMi mi = input["type"];
|
GdbMi mi = input["type"];
|
||||||
if (mi.isValid())
|
if (mi.isValid())
|
||||||
setType(mi.data());
|
type = mi.data();
|
||||||
|
|
||||||
editvalue = input["editvalue"].data();
|
editvalue = input["editvalue"].data();
|
||||||
editformat = input["editformat"].data();
|
editformat = input["editformat"].data();
|
||||||
@@ -428,7 +341,7 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
|
|||||||
// *(class X*)0xdeadbeef for gdb.
|
// *(class X*)0xdeadbeef for gdb.
|
||||||
exp = name;
|
exp = name;
|
||||||
else
|
else
|
||||||
exp = "*(" + gdbQuoteTypes(type) + "*)" + hexAddress();
|
exp = "*(" + type + "*)" + hexAddress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,7 +410,7 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
|
|||||||
const GdbMi &subinput = children.children().at(i);
|
const GdbMi &subinput = children.children().at(i);
|
||||||
WatchItem *child = new WatchItem;
|
WatchItem *child = new WatchItem;
|
||||||
if (childType.isValid())
|
if (childType.isValid())
|
||||||
child->setType(childType.data());
|
child->type = childType.data();
|
||||||
if (childNumChild.isValid())
|
if (childNumChild.isValid())
|
||||||
child->setHasChildren(childNumChild.toInt() > 0);
|
child->setHasChildren(childNumChild.toInt() > 0);
|
||||||
GdbMi name = subinput["name"];
|
GdbMi name = subinput["name"];
|
||||||
@@ -516,7 +429,7 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
|
|||||||
child->iname = this->iname + '.' + nn;
|
child->iname = this->iname + '.' + nn;
|
||||||
if (addressStep) {
|
if (addressStep) {
|
||||||
child->address = addressBase + i * addressStep;
|
child->address = addressBase + i * addressStep;
|
||||||
child->exp = "*(" + gdbQuoteTypes(child->type) + "*)0x"
|
child->exp = "*(" + child->type + "*)0x"
|
||||||
+ QString::number(child->address, 16);
|
+ QString::number(child->address, 16);
|
||||||
}
|
}
|
||||||
QString key = subinput["key"].data();
|
QString key = subinput["key"].data();
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ public:
|
|||||||
|
|
||||||
void setError(const QString &);
|
void setError(const QString &);
|
||||||
void setValue(const QString &);
|
void setValue(const QString &);
|
||||||
void setType(const QString &, bool guessChildrenFromType = true);
|
|
||||||
|
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
|
||||||
|
|||||||
@@ -220,22 +220,6 @@ bool isKeyWord(const QString &exp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool startsWithDigit(const QString &str)
|
|
||||||
{
|
|
||||||
return !str.isEmpty() && str.at(0).isDigit();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString stripPointerType(QString type)
|
|
||||||
{
|
|
||||||
if (type.endsWith('*'))
|
|
||||||
type.chop(1);
|
|
||||||
if (type.endsWith("* const"))
|
|
||||||
type.chop(7);
|
|
||||||
if (type.endsWith(' '))
|
|
||||||
type.chop(1);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format a hex address with colons as in the memory editor.
|
// Format a hex address with colons as in the memory editor.
|
||||||
QString formatToolTipAddress(quint64 a)
|
QString formatToolTipAddress(quint64 a)
|
||||||
{
|
{
|
||||||
@@ -256,61 +240,5 @@ QString formatToolTipAddress(quint64 a)
|
|||||||
return "0x" + rc;
|
return "0x" + rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString gdbQuoteTypes(const QString &type)
|
|
||||||
{
|
|
||||||
// gdb does not understand sizeof(Core::IDocument*).
|
|
||||||
// "sizeof('Core::IDocument*')" is also not acceptable,
|
|
||||||
// it needs to be "sizeof('Core::IDocument'*)"
|
|
||||||
//
|
|
||||||
// We never will have a perfect solution here (even if we had a full blown
|
|
||||||
// C++ parser as we do not have information on what is a type and what is
|
|
||||||
// a variable name. So "a<b>::c" could either be two comparisons of values
|
|
||||||
// 'a', 'b' and '::c', or a nested type 'c' in a template 'a<b>'. We
|
|
||||||
// assume here it is the latter.
|
|
||||||
//return type;
|
|
||||||
|
|
||||||
// (*('myns::QPointer<myns::QObject>*'*)0x684060)" is not acceptable
|
|
||||||
// (*('myns::QPointer<myns::QObject>'**)0x684060)" is acceptable
|
|
||||||
if (isPointerType(type))
|
|
||||||
return gdbQuoteTypes(stripPointerType(type)) + '*';
|
|
||||||
|
|
||||||
QString accu;
|
|
||||||
QString result;
|
|
||||||
int templateLevel = 0;
|
|
||||||
|
|
||||||
const char colon = ':';
|
|
||||||
const char singleQuote = '\'';
|
|
||||||
const char lessThan = '<';
|
|
||||||
const char greaterThan = '>';
|
|
||||||
for (int i = 0; i != type.size(); ++i) {
|
|
||||||
const QChar c = type.at(i);
|
|
||||||
if (isLetterOrNumber(c.unicode()) || c == '_' || c == colon || c == ' ') {
|
|
||||||
accu += c;
|
|
||||||
} else if (c == lessThan) {
|
|
||||||
++templateLevel;
|
|
||||||
accu += c;
|
|
||||||
} else if (c == greaterThan) {
|
|
||||||
--templateLevel;
|
|
||||||
accu += c;
|
|
||||||
} else if (templateLevel > 0) {
|
|
||||||
accu += c;
|
|
||||||
} else {
|
|
||||||
if (accu.contains(colon) || accu.contains(lessThan))
|
|
||||||
result += singleQuote + accu + singleQuote;
|
|
||||||
else
|
|
||||||
result += accu;
|
|
||||||
accu.clear();
|
|
||||||
result += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (accu.contains(colon) || accu.contains(lessThan))
|
|
||||||
result += singleQuote + accu + singleQuote;
|
|
||||||
else
|
|
||||||
result += accu;
|
|
||||||
//qDebug() << "GDB_QUOTING" << type << " TO " << result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|||||||
@@ -40,10 +40,6 @@ bool hasLetterOrNumber(const QString &exp);
|
|||||||
bool hasSideEffects(const QString &exp);
|
bool hasSideEffects(const QString &exp);
|
||||||
bool isKeyWord(const QString &exp);
|
bool isKeyWord(const QString &exp);
|
||||||
bool isPointerType(const QString &type);
|
bool isPointerType(const QString &type);
|
||||||
bool isCharPointerType(const QString &type);
|
|
||||||
bool startsWithDigit(const QString &str);
|
|
||||||
QString stripPointerType(QString type);
|
|
||||||
QString gdbQuoteTypes(const QString &type);
|
|
||||||
bool isFloatType(const QString &type);
|
bool isFloatType(const QString &type);
|
||||||
bool isIntOrFloatType(const QString &type);
|
bool isIntOrFloatType(const QString &type);
|
||||||
bool isIntType(const QString &type);
|
bool isIntType(const QString &type);
|
||||||
|
|||||||
Reference in New Issue
Block a user