diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp index dcd016495a64194906bbe254d17ee3751f6e5506..32a1e0eb666da113fbb48cc731280ee701f9856f 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.cpp +++ b/share/qtcreator/gdbmacros/gdbmacros.cpp @@ -888,10 +888,13 @@ static inline void dumpStdWStringValue(QDumper &d, const std::wstring &str) } // Tell the calling routine whether a global "childnumchild" attribute makes sense -enum InnerValueResult { InnerValueNotHandled, - InnerValueChildrenSpecified, - InnerValueNoFurtherChildren, - InnerValueFurtherChildren }; +enum InnerValueResult +{ + InnerValueNotHandled, + InnerValueChildrenSpecified, + InnerValueNoFurtherChildren, + InnerValueFurtherChildren +}; static inline void dumpChildNumChildren(QDumper &d, InnerValueResult innerValueResult) { @@ -909,12 +912,39 @@ static inline void dumpChildNumChildren(QDumper &d, InnerValueResult innerValueR } // Called by templates, so, not static. +static void qDumpInnerQCharValue(QDumper &d, QChar c, const char *field) +{ + char buf[30]; + sprintf(buf, "'?', ucs=%d", c.unicode()); + if (c.isPrint() && c.unicode() < 127) + buf[1] = char(c.unicode()); + d.putCommaIfNeeded(); + d.putItem(field, buf); + d.putItem("numchild", 0); +} + +static void qDumpInnerCharValue(QDumper &d, char c, const char *field) +{ + char buf[30]; + sprintf(buf, "'?', ascii=%d", c); + if (QChar(c).isPrint() && c < 127) + buf[1] = c; + d.putCommaIfNeeded(); + d.putItem(field, buf); + d.putItem("numchild", 0); +} + InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr, const char *field = "value") { - char buf[30]; type = stripNamespace(type); switch (type[1]) { + case 'h': + if (isEqual(type, "char")) { + qDumpInnerCharValue(d, *(char *)addr, field); + return InnerValueNoFurtherChildren; + } + return InnerValueNotHandled; case 'l': if (isEqual(type, "float")) { d.putItem(field, *(float*)addr); return InnerValueNoFurtherChildren; } @@ -924,12 +954,12 @@ InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, const void d.putItem(field, *(int*)addr); return InnerValueNoFurtherChildren; } - if (isEqual(type, "unsigned")) { + if (isEqual(type, "unsigned") || isEqual(type, "unsigned int")) { d.putItem(field, *(unsigned int*)addr); return InnerValueNoFurtherChildren; } - if (isEqual(type, "unsigned int")) { - d.putItem(field, *(unsigned int*)addr); + if (isEqual(type, "unsigned char")) { + qDumpInnerCharValue(d, *(char *)addr, field); return InnerValueNoFurtherChildren; } if (isEqual(type, "unsigned long")) { @@ -973,13 +1003,7 @@ InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, const void return InnerValueNotHandled; case 'C': if (isEqual(type, "QChar")) { - d.putCommaIfNeeded(); - QChar c = *(QChar *)addr; - sprintf(buf, "'?', ucs=%d", c.unicode()); - if (c.isPrint() && c.unicode() < 127) - buf[1] = char(c.unicode()); - d.putItem(field, buf); - d.putItem("numchild", 0); + qDumpInnerQCharValue(d, *(QChar*)addr, field); return InnerValueNoFurtherChildren; } return InnerValueNotHandled; @@ -1014,8 +1038,8 @@ InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, const void case 'S': if (isEqual(type, "QString")) { d.putCommaIfNeeded(); - d.put(field).put("encoded=\"2\""); d.putItem(field, *(QString*)addr); + d.put(',').put(field).put("encoded=\"2\""); return InnerValueNoFurtherChildren; } return InnerValueNotHandled; @@ -1200,9 +1224,9 @@ static void qDumpQByteArray(QDumper &d) d.putItem("valueencoded", "1"); d.putItem("type", NS"QByteArray"); d.putItem("numchild", ba.size()); - d.putItem("childtype", "char"); - d.putItem("childnumchild", "0"); if (d.dumpChildren) { + d.putItem("childtype", "char"); + d.putItem("childnumchild", "0"); d.beginChildren(); char buf[20]; for (int i = 0; i != ba.size(); ++i) { @@ -1221,13 +1245,7 @@ static void qDumpQByteArray(QDumper &d) static void qDumpQChar(QDumper &d) { - QChar c = *(QChar *)d.data; - char buf[100]; - sprintf(buf, "'?', ucs=%d", c.unicode()); - if (c.isPrint() && c.unicode() < 127) - buf[1] = char(c.unicode()); - d.putItem("value", buf); - d.putItem("numchild", 0); + qDumpInnerQCharValue(d, *reinterpret_cast<const QChar *>(d.data), "value"); d.disarm(); } @@ -1628,9 +1646,8 @@ static void qDumpQList(QDumper &d) d.putItemCount("value", n); d.putItem("valuedisabled", "true"); d.putItem("numchild", n); - d.putItem("childtype", d.innertype); - InnerValueResult innerValueResult = InnerValueChildrenSpecified; if (d.dumpChildren) { + InnerValueResult innerValueResult = InnerValueChildrenSpecified; unsigned innerSize = d.extraInt[0]; bool innerTypeIsPointer = isPointerType(d.innertype); QByteArray strippedInnerType = stripPointerType(d.innertype); @@ -1678,8 +1695,8 @@ static void qDumpQList(QDumper &d) if (n < nn) d.putEllipsis(); d.endChildren(); + dumpChildNumChildren(d, innerValueResult); } - dumpChildNumChildren(d, innerValueResult); d.disarm(); } @@ -1697,7 +1714,6 @@ static void qDumpQLinkedList(QDumper &d) d.putItemCount("value", n); d.putItem("valuedisabled", "true"); d.putItem("numchild", n); - d.putItem("childtype", d.innertype); InnerValueResult innerValueResult = InnerValueChildrenSpecified; if (d.dumpChildren) { //unsigned innerSize = d.extraInt[0]; @@ -1973,21 +1989,33 @@ static void qDumpQObject(QDumper &d) d.beginChildren(); d.beginHash(); d.putItem("name", "properties"); - d.putItem("addr", d.data); + // using 'addr' does not work as 'exp' is recreated as + // (type *)addr, and here we have different 'types': + // QObject vs QObjectPropertyList! + //d.putItem("addr", d.data); + d.beginItem("exp"); + d.put("*(class "NSX"QObject"NSY"*)").put(d.data); + d.endItem(); d.putItem("type", NS"QObjectPropertyList"); d.putItemCount("value", mo->propertyCount()); d.putItem("numchild", mo->propertyCount()); d.endHash(); d.beginHash(); d.putItem("name", "signals"); - d.putItem("addr", d.data); + //d.putItem("addr", d.data); + d.beginItem("exp"); + d.put("*(class "NSX"QObject"NSY"*)").put(d.data); + d.endItem(); d.putItem("type", NS"QObjectSignalList"); d.putItemCount("value", signalCount); d.putItem("numchild", signalCount); d.endHash(); d.beginHash(); d.putItem("name", "slots"); - d.putItem("addr", d.data); + //d.putItem("addr", d.data); + d.beginItem("exp"); + d.put("*(class "NSX"QObject"NSY"*)").put(d.data); + d.endItem(); d.putItem("type", NS"QObjectSlotList"); d.putItemCount("value", slotCount); d.putItem("numchild", slotCount); @@ -1996,7 +2024,10 @@ static void qDumpQObject(QDumper &d) if (!objectChildren.empty()) { d.beginHash(); d.putItem("name", "children"); - d.putItem("addr", d.data); + //d.putItem("addr", d.data); + d.beginItem("exp"); + d.put("*(class "NSX"QObject"NSY"*)").put(d.data); + d.endItem(); d.putItem("type", NS"QObjectChildList"); d.putItemCount("value", objectChildren.size()); d.putItem("numchild", objectChildren.size()); @@ -2316,9 +2347,9 @@ static void qDumpQObjectMethodList(QDumper &d) d.putItem("addr", "<synthetic>"); d.putItem("type", NS"QObjectMethodList"); d.putItem("numchild", mo->methodCount()); - d.putItem("childtype", "QMetaMethod::Method"); - d.putItem("childnumchild", "0"); if (d.dumpChildren) { + d.putItem("childtype", "QMetaMethod::Method"); + d.putItem("childnumchild", "0"); d.beginChildren(); for (int i = 0; i != mo->methodCount(); ++i) { const QMetaMethod & method = mo->method(i); @@ -2731,9 +2762,9 @@ static void qDumpQStringList(QDumper &d) d.putItemCount("value", n); d.putItem("valuedisabled", "true"); d.putItem("numchild", n); - d.putItem("childtype", NS"QString"); - d.putItem("childnumchild", "0"); if (d.dumpChildren) { + d.putItem("childtype", NS"QString"); + d.putItem("childnumchild", "0"); if (n > 1000) n = 1000; d.beginChildren(); @@ -3048,8 +3079,8 @@ static void qDumpStdSetHelper(QDumper &d) d.putItem("numchild", nn); d.putItem("valueoffset", d.extraInt[0]); - InnerValueResult innerValueResult = InnerValueChildrenSpecified; if (d.dumpChildren) { + InnerValueResult innerValueResult = InnerValueChildrenSpecified; int valueOffset = 0; // d.extraInt[0]; QByteArray strippedInnerType = stripPointerType(d.innertype); const char *stripped = @@ -3071,8 +3102,8 @@ static void qDumpStdSetHelper(QDumper &d) if (it != set.end()) d.putEllipsis(); d.endChildren(); + dumpChildNumChildren(d, innerValueResult); } - dumpChildNumChildren(d, innerValueResult); d.disarm(); } @@ -3159,8 +3190,8 @@ static void qDumpStdVector(QDumper &d) d.putItemCount("value", n); d.putItem("valuedisabled", "true"); d.putItem("numchild", n); - InnerValueResult innerValueResult = InnerValueChildrenSpecified; if (d.dumpChildren) { + InnerValueResult innerValueResult = InnerValueChildrenSpecified; unsigned innersize = d.extraInt[0]; QByteArray strippedInnerType = stripPointerType(d.innertype); const char *stripped = @@ -3178,8 +3209,8 @@ static void qDumpStdVector(QDumper &d) if (n < nn) d.putEllipsis(); d.endChildren(); + dumpChildNumChildren(d, innerValueResult); } - dumpChildNumChildren(d, innerValueResult); d.disarm(); } diff --git a/tests/auto/debugger/main.cpp b/tests/auto/debugger/main.cpp index eb79b6180c55e8eed7730b814e8881421065865f..08a00fe82f319bb50b5da8ac338f2c51b5a84433 100644 --- a/tests/auto/debugger/main.cpp +++ b/tests/auto/debugger/main.cpp @@ -75,6 +75,16 @@ static const char jsont1[] = "{\"Size\":100564,\"UID\":0,\"GID\":0,\"Permissions\":33261," "\"ATime\":1242370878000,\"MTime\":1239154689000}"; +struct Int3 { + Int3() { i1 = 42; i2 = 43; i3 = 44; } + int i1, i2, i3; +}; + +struct QString3 { + QString3() { s1 = "a"; s2 = "b"; s3 = "c"; } + QString s1, s2, s3; +}; + class tst_Debugger : public QObject { Q_OBJECT @@ -114,6 +124,7 @@ private slots: void dumperCompatibility(); void dumpQHash(); + void dumpQList(); void dumpQObject(); void dumpQString(); void dumpQVariant(); @@ -388,6 +399,76 @@ void tst_Debugger::dumpQHash() hash.insert("!", QList<int>() << 1 << 2); } +void tst_Debugger::dumpQList() +{ + QList<int> ilist; + testDumper("value='<0 items>',valuedisabled='true',numchild='0'," + "internal='1',childtype='int',children=[]", + &ilist, NS"QList", true, "int"); + ilist.append(1); + ilist.append(2); + testDumper("value='<2 items>',valuedisabled='true',numchild='2'," + "internal='1',childtype='int',children=[" + "{name='0',addr='" + str(&ilist.at(0)) + "',value='1'}," + "{name='1',addr='" + str(&ilist.at(1)) + "',value='2'}]," + "childnumchild='0'", + &ilist, NS"QList", true, "int"); + + QList<char> clist; + testDumper("value='<0 items>',valuedisabled='true',numchild='0'," + "internal='1',childtype='char',children=[]", + &clist, NS"QList", true, "char"); + clist.append('a'); + clist.append('b'); + testDumper("value='<2 items>',valuedisabled='true',numchild='2'," + "internal='1',childtype='char',children=[" + "{name='0',addr='" + str(&clist.at(0)) + "'," + "value=''a', ascii=97',numchild='0'}," + "{name='1',addr='" + str(&clist.at(1)) + "'," + "value=''b', ascii=98',numchild='0'}]," + "childnumchild='0'", + &clist, NS"QList", true, "char"); + + QList<QString> slist; + testDumper("value='<0 items>',valuedisabled='true',numchild='0'," + "internal='1',childtype='QString',children=[]", + &slist, NS"QList", true, "QString"); + slist.append("a"); + slist.append("b"); + testDumper("value='<2 items>',valuedisabled='true',numchild='2'," + "internal='1',childtype='QString',children=[" + "{name='0',addr='" + str(&slist.at(0)) + "'," + "value='YQA=',valueencoded='2'}," + "{name='1',addr='" + str(&slist.at(1)) + "'," + "value='YgA=',valueencoded='2'}]," + "childnumchild='0'", + &slist, NS"QList", true, "QString"); + + QList<Int3> i3list; + testDumper("value='<0 items>',valuedisabled='true',numchild='0'," + "internal='0',childtype='Int3',children=[]", + &i3list, NS"QList", true, "Int3"); + i3list.append(Int3()); + i3list.append(Int3()); + testDumper("value='<2 items>',valuedisabled='true',numchild='2'," + "internal='0',childtype='Int3',children=[" + "{name='0',addr='" + str(&i3list.at(0)) + "'}," + "{name='1',addr='" + str(&i3list.at(1)) + "'}]", + &i3list, NS"QList", true, "Int3"); + + QList<QString3> s3list; + testDumper("value='<0 items>',valuedisabled='true',numchild='0'," + "internal='0',childtype='QString3',children=[]", + &s3list, NS"QList", true, "QString3"); + s3list.append(QString3()); + s3list.append(QString3()); + testDumper("value='<2 items>',valuedisabled='true',numchild='2'," + "internal='0',childtype='QString3',children=[" + "{name='0',addr='" + str(&s3list.at(0)) + "'}," + "{name='1',addr='" + str(&s3list.at(1)) + "'}]", + &s3list, NS"QList", true, "QString3"); +} + void tst_Debugger::dumpQObject() { QObject parent; @@ -402,7 +483,7 @@ void tst_Debugger::dumpQObject() "value='<2 items>',numchild='2'}," "{name='slots',exp='*(class '$T'*)$A',type='$TSlotList'," "value='<2 items>',numchild='2'}," - "{name='parent',value='0x0',type='$T *'}," + "{name='parent',value='0x0',type='$T *',numchild='0'}," "{name='className',value='QObject',type='',numchild='0'}]", &parent, NS"QObject", true); /* @@ -432,7 +513,7 @@ void tst_Debugger::dumpQObject() "value='<2 items>',numchild='2'}," "{name='parent',addr='" + str(&parent) + "'," "value='QQAgAFAAYQByAGUAbgB0AA==',valueencoded='2',type='$T'," - "displayedtype='QObject'}," + "displayedtype='QObject',numchild='1'}," "{name='className',value='QObject',type='',numchild='0'}]"; testDumper(ba, &child, NS"QObject", true); QObject::connect(&child, SIGNAL(destroyed()), qApp, SLOT(quit())); diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 7686619734ae4cee60119430e3c5a927207b7167..c230f2733fb11edf781a164371e20ea975539858 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -999,12 +999,35 @@ void testQVectorOfQList() } +class Goo +{ +public: + Goo(const QString& str, const int n) : + str_(str), n_(n) + { + } +private: + QString str_; + int n_; +}; + +typedef QList<Goo> GooList; + void testNoArgumentName(int i, int, int k) { + GooList list; + list.append(Goo("Hello", 1)); + list.append(Goo("World", 2)); + + QList<Goo> list2; + list2.append(Goo("Hello", 1)); + list2.append(Goo("World", 2)); + i = 1000; k = 2000; ++k; ++k; + } void foo() {}