From b295aec1ad51576d7590c7ccdc2708f7ffceaec3 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Thu, 25 Jun 2009 15:00:57 +0200
Subject: [PATCH] debugger: fix several small issues in the dumper code

Fix typo in QChar helper.
Add a auto tests for some of the dumpers.
Make the dumpers compilable for Qt < 4.5 for better regression tests.
Make manual tests compile with Qt < 4.5.
---
 share/qtcreator/gdbmacros/gdbmacros.cpp | 104 +++++++------
 share/qtcreator/gdbmacros/gdbmacros.h   |  46 ++++++
 src/plugins/debugger/watchhandler.cpp   |   5 +-
 tests/auto/debugger/debugger.pro        |   8 +-
 tests/auto/debugger/main.cpp            | 192 +++++++++++++++++++++++-
 tests/manual/gdbdebugger/simple/app.cpp |   8 +
 6 files changed, 310 insertions(+), 53 deletions(-)
 create mode 100644 share/qtcreator/gdbmacros/gdbmacros.h

diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp
index fa55c4d7bc8..207f1c7d15d 100644
--- a/share/qtcreator/gdbmacros/gdbmacros.cpp
+++ b/share/qtcreator/gdbmacros/gdbmacros.cpp
@@ -44,11 +44,14 @@
 #include <QtCore/QObject>
 #include <QtCore/QPointer>
 #include <QtCore/QString>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QSharedDataPointer>
 #include <QtCore/QTextCodec>
 #include <QtCore/QVector>
+
+#if QT_VERSION >= 0x040500
+#include <QtCore/QSharedPointer>
+#include <QtCore/QSharedDataPointer>
 #include <QtCore/QWeakPointer>
+#endif
 
 int qtGhVersion = QT_VERSION;
 
@@ -180,6 +183,9 @@ struct Sender { QObject *sender; int signal; int ref; };
         int method;
         uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
         QBasicAtomicPointer<int> argumentTypes;
+        //senders linked list
+        //Connection *next;
+        //Connection **prev;
     };
 
     typedef QList<Connection *> ConnectionList;
@@ -191,11 +197,11 @@ struct Sender { QObject *sender; int signal; int ref; };
     int signalAt(const SenderList &l, int i) { return l.at(i)->method; }
 #endif
 
-class QObjectPrivate : public QObjectData
+class ObjectPrivate : public QObjectData
 {
 public:
-    QObjectPrivate() {}
-    virtual ~QObjectPrivate() {}
+    ObjectPrivate() {}
+    virtual ~ObjectPrivate() {}
 
     QList<QObject *> pendingChildInsertedEvents;
     void *threadData;
@@ -222,10 +228,18 @@ QT_END_NAMESPACE
 
 // This can be mangled typenames of nested templates, each char-by-char
 // comma-separated integer list...
-Q_DECL_EXPORT char qDumpInBuffer[10000];
-
 // The output buffer.
-Q_DECL_EXPORT char qDumpOutBuffer[1000000];
+#ifdef MACROSDEBUG
+    Q_DECL_EXPORT char xDumpInBuffer[10000];
+    Q_DECL_EXPORT char xDumpOutBuffer[1000000];
+    #define inBuffer xDumpInBuffer
+    #define outBuffer xDumpOutBuffer
+#else
+    Q_DECL_EXPORT char qDumpInBuffer[10000];
+    Q_DECL_EXPORT char qDumpOutBuffer[1000000];
+    #define inBuffer qDumpInBuffer
+    #define outBuffer qDumpOutBuffer
+#endif
 
 namespace {
 
@@ -476,15 +490,15 @@ QDumper::QDumper()
 {
     success = false;
     full = false;
-    qDumpOutBuffer[0] = 'f'; // marks output as 'wrong' 
+    outBuffer[0] = 'f'; // marks output as 'wrong' 
     pos = 1;
 }
 
 QDumper::~QDumper()
 {
-    qDumpOutBuffer[pos++] = '\0';
+    outBuffer[pos++] = '\0';
     if (success)
-        qDumpOutBuffer[0] = (full ? '+' : 't');
+        outBuffer[0] = (full ? '+' : 't');
 }
 
 void QDumper::setupTemplateParameters()
@@ -510,49 +524,49 @@ void QDumper::setupTemplateParameters()
 QDumper &QDumper::operator<<(unsigned long long c)
 {
     checkFill();
-    pos += sprintf(qDumpOutBuffer + pos, "%llu", c);
+    pos += sprintf(outBuffer + pos, "%llu", c);
     return *this;
 }
 
 QDumper &QDumper::operator<<(unsigned long c)
 {
     checkFill();
-    pos += sprintf(qDumpOutBuffer + pos, "%lu", c);
+    pos += sprintf(outBuffer + pos, "%lu", c);
     return *this;
 }
 
 QDumper &QDumper::operator<<(float d)
 {
     checkFill();
-    pos += sprintf(qDumpOutBuffer + pos, "%f", d);
+    pos += sprintf(outBuffer + pos, "%f", d);
     return *this;
 }
 
 QDumper &QDumper::operator<<(double d)
 {
     checkFill();
-    pos += sprintf(qDumpOutBuffer + pos, "%f", d);
+    pos += sprintf(outBuffer + pos, "%f", d);
     return *this;
 }
 
 QDumper &QDumper::operator<<(unsigned int i)
 {
     checkFill();
-    pos += sprintf(qDumpOutBuffer + pos, "%u", i);
+    pos += sprintf(outBuffer + pos, "%u", i);
     return *this;
 }
 
 QDumper &QDumper::operator<<(long c)
 {
     checkFill();
-    pos += sprintf(qDumpOutBuffer + pos, "%ld", c);
+    pos += sprintf(outBuffer + pos, "%ld", c);
     return *this;
 }
 
 QDumper &QDumper::operator<<(int i)
 {
     checkFill();
-    pos += sprintf(qDumpOutBuffer + pos, "%d", i);
+    pos += sprintf(outBuffer + pos, "%d", i);
     return *this;
 }
 
@@ -576,7 +590,7 @@ QDumper &QDumper::operator<<(const void *p)
 
 void QDumper::checkFill()
 {
-    if (pos >= int(sizeof(qDumpOutBuffer)) - 100)
+    if (pos >= int(sizeof(outBuffer)) - 100)
         full = true;
 }
 
@@ -584,14 +598,14 @@ void QDumper::put(char c)
 {
     checkFill();
     if (!full)
-        qDumpOutBuffer[pos++] = c;
+        outBuffer[pos++] = c;
 }
 
 void QDumper::addCommaIfNeeded()
 {
     if (pos == 0)
         return;
-    char c = qDumpOutBuffer[pos - 1];
+    char c = outBuffer[pos - 1];
     if (c == '}' || c == '"' || c == ']')
         put(',');
 }
@@ -736,8 +750,8 @@ void QDumper::putEllipsis()
 #define DUMPUNKNOWN_MESSAGE "<internal error>"
 static void qDumpUnknown(QDumper &d, const char *why = 0)
 {
-    P(d, "iname", d.iname);
-    P(d, "addr", d.data);
+    //P(d, "iname", d.iname);
+    //P(d, "addr", d.data);
     if (!why)
         why = DUMPUNKNOWN_MESSAGE;
     P(d, "value", why);
@@ -792,7 +806,7 @@ static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr
             if (isEqual(type, "QChar")) {
                 d.addCommaIfNeeded();
                 QChar c = *(QChar *)addr;
-                char str[] = "'?', usc=\0";
+                char str[] = "'?', ucs=\0";
                 if (c.isPrint() && c.unicode() < 127)
                     str[1] = char(c.unicode());
                 P(d, field, str << c.unicode());
@@ -1007,7 +1021,7 @@ static void qDumpQChar(QDumper &d)
 {
     d.addCommaIfNeeded();
     QChar c = *(QChar *)d.data;
-    char str[] = "'?', usc=\0";
+    char str[] = "'?', ucs=\0";
     if (c.isPrint() && c.unicode() < 127)
         str[1] = char(c.unicode());
     P(d, "value", str << c.unicode());
@@ -1740,7 +1754,7 @@ static void qDumpQObject(QDumper &d)
 #if 0
         d.beginHash();
             P(d, "name", "senders");
-            P(d, "exp", "(*(class '"NS"QObjectPrivate'*)" << dfunc(ob) << ")->senders");
+            P(d, "exp", "(*(class '"NS"ObjectPrivate'*)" << dfunc(ob) << ")->senders");
             P(d, "type", NS"QList<"NS"QObjectPrivateSender>");
         d.endHash();
 #endif
@@ -1862,7 +1876,7 @@ const char * qConnectionTypes[] ={
 static const ConnectionList &qConnectionList(const QObject *ob, int signalNumber)
 {
     static const ConnectionList emptyList;
-    const QObjectPrivate *p = reinterpret_cast<const QObjectPrivate *>(dfunc(ob));
+    const ObjectPrivate *p = reinterpret_cast<const ObjectPrivate *>(dfunc(ob));
     if (!p->connectionLists)
         return emptyList;
     typedef QVector<ConnectionList> ConnLists;
@@ -1963,7 +1977,7 @@ static void qDumpQObjectSlot(QDumper &d)
         d << ",children=[";
         int numchild = 0;
         const QObject *ob = reinterpret_cast<const QObject *>(d.data);
-        const QObjectPrivate *p = reinterpret_cast<const QObjectPrivate *>(dfunc(ob));
+        const ObjectPrivate *p = reinterpret_cast<const ObjectPrivate *>(dfunc(ob));
         for (int s = 0; s != p->senders.size(); ++s) {
             const QObject *sender = senderAt(p->senders, s);
             int signal = signalAt(p->senders, s);
@@ -2003,7 +2017,7 @@ static void qDumpQObjectSlotList(QDumper &d)
 {
     const QObject *ob = reinterpret_cast<const QObject *>(d.data);
 #if QT_VERSION >= 0x040400
-    const QObjectPrivate *p = reinterpret_cast<const QObjectPrivate *>(dfunc(ob));
+    const ObjectPrivate *p = reinterpret_cast<const ObjectPrivate *>(dfunc(ob));
 #endif
     const QMetaObject *mo = ob->metaObject();
 
@@ -2011,11 +2025,10 @@ static void qDumpQObjectSlotList(QDumper &d)
     for (int i = mo->methodCount(); --i >= 0; )
         count += (mo->method(i).methodType() == QMetaMethod::Slot);
 
-    P(d, "addr", d.data);
     P(d, "numchild", count);
-#if QT_VERSION >= 0x040400
     if (d.dumpChildren) {
         d << ",children=[";
+#if QT_VERSION >= 0x040400
         for (int i = 0; i != mo->methodCount(); ++i) {
             const QMetaMethod & method = mo->method(i);
             if (method.methodType() == QMetaMethod::Slot) {
@@ -2042,9 +2055,9 @@ static void qDumpQObjectSlotList(QDumper &d)
                 d.endHash();
             }
         }
+#endif
         d << "]";
     }
-#endif
     d.disarm();
 }
 
@@ -2105,6 +2118,7 @@ static void qDumpQSet(QDumper &d)
     d.disarm();
 }
 
+#if QT_VERSION >= 0x040500
 static void qDumpQSharedPointer(QDumper &d)
 {
     const QSharedPointer<int> &ptr =
@@ -2143,6 +2157,7 @@ static void qDumpQSharedPointer(QDumper &d)
     }
     d.disarm();
 }
+#endif // QT_VERSION >= 0x040500
 
 static void qDumpQString(QDumper &d)
 {
@@ -2342,6 +2357,7 @@ static void qDumpQVector(QDumper &d)
     d.disarm();
 }
 
+#if QT_VERSION >= 0x040500
 static void qDumpQWeakPointer(QDumper &d)
 {
     const int v = sizeof(void *);
@@ -2379,6 +2395,7 @@ static void qDumpQWeakPointer(QDumper &d)
     }
     d.disarm();
 }
+#endif // QT_VERSION >= 0x040500
 
 static void qDumpStdList(QDumper &d)
 {
@@ -2645,7 +2662,6 @@ static void qDumpStdVectorBool(QDumper &d)
 
 static void handleProtocolVersion2and3(QDumper & d)
 {
-
     if (!d.outertype[0]) {
         qDumpUnknown(d);
         return;
@@ -2772,8 +2788,10 @@ static void handleProtocolVersion2and3(QDumper & d)
         case 'S':
             if (isEqual(type, "QSet"))
                 qDumpQSet(d);
+            #if QT_VERSION >= 0x040500
             else if (isEqual(type, "QSharedPointer"))
                 qDumpQSharedPointer(d);
+            #endif
             else if (isEqual(type, "QString"))
                 qDumpQString(d);
             else if (isEqual(type, "QStringList"))
@@ -2810,8 +2828,11 @@ static void handleProtocolVersion2and3(QDumper & d)
                 qDumpQVector(d);
             break;
         case 'W':
+            #if QT_VERSION >= 0x040500
             if (isEqual(type, "QWeakPointer"))
                 qDumpQWeakPointer(d);
+            #endif
+            break;
     }
 
     if (!d.success)
@@ -2832,11 +2853,7 @@ void *qDumpObjectData440(
     int protocolVersion,
     int token,
     void *data,
-#ifdef Q_CC_MSVC // CDB cannot handle boolean parameters
     int dumpChildren,
-#else
-    bool dumpChildren,
-#endif
     int extraInt0,
     int extraInt1,
     int extraInt2,
@@ -2856,6 +2873,7 @@ void *qDumpObjectData440(
             "\""NS"QAbstractItem\","
             "\""NS"QAbstractItemModel\","
             "\""NS"QByteArray\","
+            "\""NS"QChar\","
             "\""NS"QDateTime\","
             "\""NS"QDir\","
             "\""NS"QFile\","
@@ -2870,9 +2888,6 @@ void *qDumpObjectData440(
             "\""NS"QMap\","
             "\""NS"QMapNode\","
             "\""NS"QModelIndex\","
-#if QT_VERSION >= 0x040500
-            "\""NS"QMultiMap\","
-#endif
             "\""NS"QObject\","
             "\""NS"QObjectMethodList\","   // hack to get nested properties display
             "\""NS"QObjectPropertyList\","
@@ -2882,13 +2897,16 @@ void *qDumpObjectData440(
             "\""NS"QObjectSlotList\","
             // << "\""NS"QRegion\","
             "\""NS"QSet\","
-            "\""NS"QSharedPointer\","
             "\""NS"QString\","
             "\""NS"QStringList\","
             "\""NS"QTextCodec\","
             "\""NS"QVariant\","
             "\""NS"QVector\","
+#if QT_VERSION >= 0x040500
+            "\""NS"QMultiMap\","
+            "\""NS"QSharedPointer\","
             "\""NS"QWeakPointer\","
+#endif
 #if USE_QT_GUI
             "\""NS"QWidget\","
 #endif
@@ -2947,7 +2965,7 @@ void *qDumpObjectData440(
         d.extraInt[2]     = extraInt2;
         d.extraInt[3]     = extraInt3;
 
-        const char *inbuffer = qDumpInBuffer;
+        const char *inbuffer = inBuffer;
         d.outertype = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
         d.iname     = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
         d.exp       = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
@@ -2960,5 +2978,5 @@ void *qDumpObjectData440(
     else {
         qDebug() << "Unsupported protocol version" << protocolVersion;
     }
-    return qDumpOutBuffer;
+    return outBuffer;
 }
diff --git a/share/qtcreator/gdbmacros/gdbmacros.h b/share/qtcreator/gdbmacros/gdbmacros.h
new file mode 100644
index 00000000000..8372d160e0c
--- /dev/null
+++ b/share/qtcreator/gdbmacros/gdbmacros.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+**
+**************************************************************************/
+
+#ifndef GDBMACROS_H
+#define GDBMACROS_H
+
+#ifdef MACROSDEBUG
+Q_DECL_EXPORT extern char xDumpInBuffer[];
+Q_DECL_EXPORT extern char xDumpOutBuffer[];
+#else
+Q_DECL_EXPORT extern char qDumpInBuffer[];
+Q_DECL_EXPORT extern char qDumpOutBuffer[];
+#endif
+
+extern "C" Q_DECL_EXPORT
+void *qDumpObjectData440(int protocolVersion, int token, void *data,
+  int dumpChildren, int extraInt0, int extraInt1, int extraInt2, int extraInt3);
+
+
+#endif // GDBMACROS_H
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 57cb69c0964..c482a5f668e 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -186,7 +186,7 @@ void WatchData::setType(const QString &str)
         setHasChildren(false);
 }
 
-void WatchData::setAddress(const QString & str)
+void WatchData::setAddress(const QString &str)
 {
     addr = str;
 }
@@ -196,8 +196,7 @@ WatchData WatchData::pointerChildPlaceHolder() const
     WatchData data1;
     data1.iname = iname + QLatin1String(".*");
     data1.name = QLatin1Char('*') + name;
-    data1
-.exp = QLatin1String("(*(") + exp + QLatin1String("))");
+    data1.exp = QLatin1String("(*(") + exp + QLatin1String("))");
     data1.type = stripPointerType(type);
     data1.setValueNeeded();
     return data1;
diff --git a/tests/auto/debugger/debugger.pro b/tests/auto/debugger/debugger.pro
index a7001a24d4d..c3a9f0b966d 100644
--- a/tests/auto/debugger/debugger.pro
+++ b/tests/auto/debugger/debugger.pro
@@ -2,12 +2,16 @@
 QT = core testlib
 
 DEBUGGERDIR = ../../../src/plugins/debugger
-UTILSDIR = ../../../src/libs
+UTILSDIR    = ../../../src/libs
+MACROSDIR   = ../../../share/qtcreator/gdbmacros
 
 SOURCES += \
     $$DEBUGGERDIR/gdb/gdbmi.cpp \
     $$DEBUGGERDIR/tcf/json.cpp \
+    $$MACROSDIR/gdbmacros.cpp \
     main.cpp \
 
-INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR
+DEFINES += MACROSDEBUG
+
+INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR $$MACROSDIR
 
diff --git a/tests/auto/debugger/main.cpp b/tests/auto/debugger/main.cpp
index 86ecf8cb03a..677eff1071a 100644
--- a/tests/auto/debugger/main.cpp
+++ b/tests/auto/debugger/main.cpp
@@ -1,13 +1,27 @@
 
-#include "gdb/gdbmi.h"
-#include "tcf/json.h"
-
 #include <QtCore/QObject>
 #include <QtCore/QProcess>
 #include <QtCore/QFileInfo>
 #include <QtTest/QtTest>
+
+#include <QtCore/private/qobject_p.h>
+
 //#include <QtTest/qtest_gui.h>
 
+#include "gdb/gdbmi.h"
+#include "tcf/json.h"
+#include "gdbmacros.h"
+
+
+#undef NS
+#ifdef QT_NAMESPACE
+#   define STRINGIFY0(s) #s
+#   define STRINGIFY1(s) STRINGIFY0(s)
+#   define NS STRINGIFY1(QT_NAMESPACE) "::"
+#else
+#   define NS ""
+#endif
+
 using namespace Debugger;
 using namespace Debugger::Internal;
 
@@ -98,6 +112,12 @@ private slots:
     void niceType();
     void niceType_data();
 
+    void dumperCompatibility();
+    void dumpQHash();
+    void dumpQObject();
+    void dumpQString();
+    void dumpStdVector();
+
 public slots:
     void runQtc();
 
@@ -154,6 +174,10 @@ void tst_Debugger::infoBreak()
     QCOMPARE(re.cap(4), QString("124"));
 }
 
+//
+// type simplification
+//
+
 static QString chopConst(QString type)
 {
    while (1) {
@@ -175,7 +199,6 @@ QString niceType(QString type)
 {
     type.replace('*', '@');
 
-    int pos;
     for (int i = 0; i < 10; ++i) {
         int start = type.indexOf("std::allocator<");
         if (start == -1)
@@ -299,6 +322,166 @@ void tst_Debugger::niceType_data()
         << "std::map<const char*, Foo>";
 }
 
+//
+// Dumpers
+//
+
+static void testDumper(QByteArray expected0, void *data, QByteArray outertype,
+    bool dumpChildren, QByteArray innertype = "", QByteArray exp = "",
+    int extraInt0 = 0, int extraInt1 = 0, int extraInt2 = 0, int extraInt3 = 0)
+{ 
+    sprintf(xDumpInBuffer, "%s%c%s%c%s%c%s%c%s%c", 
+        outertype.data(), 0, "iname", 0, exp.data(), 0,
+        innertype.data(), 0, "iname", 0);
+    void *res = qDumpObjectData440(2, 42, data, dumpChildren,
+        extraInt0, extraInt1, extraInt2, extraInt3);
+    QString expected(expected0);
+    char buf[100];
+    sprintf(buf, "%p", data);
+    if (!expected.startsWith('t') && !expected.startsWith('f'))
+        expected = "tiname='$I',addr='$A'," + expected;
+    expected.replace("$I", "iname");
+    expected.replace("$T", QByteArray(outertype));
+    expected.replace("$A", QByteArray(buf));
+    expected.replace('\'', '"');
+    QString actual____ = QString::fromLatin1(xDumpOutBuffer);
+    actual____.replace('\'', '"');
+    QCOMPARE(res, xDumpOutBuffer);
+    if (actual____ != expected) {
+        QStringList l1 = actual____.split(",");
+        QStringList l2 = expected.split(",");
+        for (int i = 0; i < l1.size() && i < l2.size(); ++i) {
+            if (l1.at(i) == l2.at(i))
+                qDebug() << "== " << l1.at(i);
+            else
+                qDebug() << "!= " << l1.at(i) << l2.at(i);
+        }
+        if (l1.size() != l2.size())
+            qDebug() << "!= size: " << l1.size() << l2.size();
+    }
+    QCOMPARE(actual____, expected);
+}
+
+QByteArray str(const void *p)
+{
+    char buf[100];
+    sprintf(buf, "%p", p);
+    return buf;
+}
+
+static const void *deref(const void *p)
+{
+    return *reinterpret_cast<const char* const*>(p);
+}
+
+void tst_Debugger::dumperCompatibility()
+{
+}
+
+void tst_Debugger::dumpQHash()
+{
+    QHash<QString, QList<int> > hash;
+    hash.insert("Hallo", QList<int>());
+    hash.insert("Welt", QList<int>() << 1);
+    hash.insert("!", QList<int>() << 1 << 2);
+    hash.insert("!", QList<int>() << 1 << 2);
+}
+
+void tst_Debugger::dumpQObject()
+{
+    QObject parent;
+    testDumper("value='',valueencoded='2',type='$T',displayedtype='QObject',"
+        "numchild='4'",
+        &parent, NS"QObject", false);
+    testDumper("value='',valueencoded='2',type='$T',displayedtype='QObject',"
+        "numchild='4',children=["
+        "{name='properties',exp='*(class '$T'*)$A',type='$TPropertyList',"
+            "value='<1 items>',numchild='1'},"
+        "{name='signals',exp='*(class '$T'*)$A',type='$TSignalList',"
+            "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='className',value='QObject',type='',numchild='0'}]",
+        &parent, NS"QObject", true);
+
+    testDumper("numchild='2',children=[{name='2',value='deleteLater()',"
+            "numchild='0',exp='*(class 'QObject'*)$A',type='QObjectSlot'},"
+        "{name='3',value='_q_reregisterTimers(void*)',"
+            "numchild='0',exp='*(class 'QObject'*)$A',type='QObjectSlot'}]",
+        &parent, NS"QObjectSlotList", true);
+
+    parent.setObjectName("A Parent");
+    testDumper("value='QQAgAFAAYQByAGUAbgB0AA==',valueencoded='2',type='$T',"
+        "displayedtype='QObject',numchild='4'",
+        &parent, NS"QObject", false);
+    QObject child(&parent);
+    testDumper("value='',valueencoded='2',type='$T',"
+        "displayedtype='QObject',numchild='4'",
+        &child, NS"QObject", false);
+    child.setObjectName("A Child");
+    QByteArray ba ="value='QQAgAEMAaABpAGwAZAA=',valueencoded='2',type='$T',"
+        "displayedtype='QObject',numchild='4',children=["
+        "{name='properties',exp='*(class '$T'*)$A',type='$TPropertyList',"
+            "value='<1 items>',numchild='1'},"
+        "{name='signals',exp='*(class '$T'*)$A',type='$TSignalList',"
+            "value='<2 items>',numchild='2'},"
+        "{name='slots',exp='*(class '$T'*)$A',type='$TSlotList',"
+            "value='<2 items>',numchild='2'},"
+        "{name='parent',addr='" + str(&parent) + "',"
+            "value='QQAgAFAAYQByAGUAbgB0AA==',valueencoded='2',type='$T',"
+            "displayedtype='QObject'},"
+        "{name='className',value='QObject',type='',numchild='0'}]";
+    testDumper(ba, &child, NS"QObject", true);
+    QObject::connect(&child, SIGNAL(destroyed()), qApp, SLOT(quit()));
+    testDumper(ba, &child, NS"QObject", true);
+    QObject::disconnect(&child, SIGNAL(destroyed()), qApp, SLOT(quit()));
+    testDumper(ba, &child, NS"QObject", true);
+    child.setObjectName("A renamed Child");
+    testDumper("value='QQAgAHIAZQBuAGEAbQBlAGQAIABDAGgAaQBsAGQA',valueencoded='2',"
+        "type='$T',displayedtype='QObject',numchild='4'",
+        &child, NS"QObject", false);
+}
+
+void tst_Debugger::dumpQString()
+{ 
+    QString s;
+    testDumper("value='',valueencoded='2',type='$T',numchild='0'",
+        &s, NS"QString", false);
+    s = "abc";
+    testDumper("value='YQBiAGMA',valueencoded='2',type='$T',numchild='0'",
+        &s, NS"QString", false);
+}
+
+void tst_Debugger::dumpStdVector()
+{
+    std::vector<std::list<int> *> vector;
+    QByteArray inner = "std::list<int> *";
+    QByteArray innerp = "std::list<int>";
+    testDumper("value='<0 items>',valuedisabled='true',numchild='0'",
+        &vector, "std::vector", false, inner, "", sizeof(std::list<int> *));
+    std::list<int> list;
+    vector.push_back(new std::list<int>(list));
+    testDumper("value='<1 items>',valuedisabled='true',numchild='1',"
+        "children=[{name='0',addr='" + str(deref(&vector[0])) + "',"
+            "saddr='" + str(deref(&vector[0])) + "',type='" + innerp + "'}]",
+        &vector, "std::vector", true, inner, "", sizeof(std::list<int> *));
+    vector.push_back(0);
+    list.push_back(45);
+    testDumper("value='<2 items>',valuedisabled='true',numchild='2',"
+        "children=[{name='0',addr='" + str(deref(&vector[0])) + "',"
+            "saddr='" + str(deref(&vector[0])) + "',type='" + innerp + "'},"
+          "{name='1',addr='" + str(&vector[1]) + "',"
+            "type='" + innerp + "',value='<null>',numchild='0'}]",
+        &vector, "std::vector", true, inner, "", sizeof(std::list<int> *));
+    vector.push_back(new std::list<int>(list));
+    vector.push_back(0);
+}
+
+//
+// Creator
+//
+
 void tst_Debugger::readStandardOutput()
 {
     qDebug() << "qtcreator-out: " << stripped(m_proc.readAllStandardOutput());
@@ -338,7 +521,6 @@ int main(int argc, char *argv[])
     QCoreApplication app(argc, argv);
     QStringList args = app.arguments();
 
-
     if (args.size() == 2 && args.at(1) == "--run-debuggee") {
         runDebuggee();
         app.exec();
diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp
index a3a004cfc52..705e5787420 100644
--- a/tests/manual/gdbdebugger/simple/app.cpp
+++ b/tests/manual/gdbdebugger/simple/app.cpp
@@ -39,7 +39,9 @@
 #include <QtCore/QThread>
 #include <QtCore/QVariant>
 #include <QtCore/QVector>
+#if QT_VERSION >= 0x040500
 #include <QtCore/QSharedPointer>
+#endif
 
 #include <QtGui/QApplication>
 #include <QtGui/QAction>
@@ -523,6 +525,7 @@ void testQSet()
     //hash.insert(ptr);
 }
 
+#if QT_VERSION >= 0x040500
 class EmployeeData : public QSharedData
 {
 public:
@@ -580,6 +583,7 @@ void testQSharedPointer()
     QWeakPointer<QString> wptr2 = wptr;
     QWeakPointer<QString> wptr3 = wptr;
 }
+#endif
 
 void stringRefTest(const QString &refstring)
 {
@@ -1131,6 +1135,8 @@ void testObject1()
     parent.setObjectName("A Parent");
     QObject child(&parent);
     child.setObjectName("A Child");
+    QObject::connect(&child, SIGNAL(destroyed()), qApp, SLOT(quit()));
+    QObject::disconnect(&child, SIGNAL(destroyed()), qApp, SLOT(quit()));
     child.setObjectName("A renamed Child");
 }
 
@@ -1198,7 +1204,9 @@ int main(int argc, char *argv[])
     testQMultiMap();
     testQString();
     testQSet();
+    #if QT_VERSION >= 0x040500
     testQSharedPointer();
+    #endif
     testQStringList();
     testStruct();
     //testThreads();
-- 
GitLab