diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index 9ea2a9aff56749af04c68e2572a8ea5e5fc31079..ac10a4dde4f45afa9e6aa4862dbd8b663ce7b84f 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -123,6 +123,7 @@ int qtGhVersion = QT_VERSION; #endif #include <list> +#include <map> #include <string> #include <vector> @@ -291,7 +292,7 @@ static bool startsWith(const char *s, const char *t) #define qCheckAccess(d) do { qProvokeSegFaultHelper = *(char*)d; } while (0) #define qCheckPointer(d) do { if (d) qProvokeSegFaultHelper = *(char*)d; } while (0) // provoke segfault unconditionally -#define qCheck(b) do { if (!b) qProvokeSegFaultHelper = *(char*)0; } while (0) +#define qCheck(b) do { if (!(b)) qProvokeSegFaultHelper = *(char*)0; } while (0) const char *stripNamespace(const char *type) { @@ -2146,6 +2147,61 @@ static void qDumpStdList(QDumper &d) d.disarm(); } +static void qDumpStdMap(QDumper &d) +{ + const std::map<int, int> &map = + *reinterpret_cast<const std::map<int, int> *>(d.data); + const char *keyType = d.templateParameters[0]; + const char *valueType = d.templateParameters[1]; + const void *p = d.data; + qCheckAccess(p); + p = deref(p); + + int nn = map.size(); + qCheck(nn >= 0); + std::map<int, int>::const_iterator it = map.begin(); + for (int i = 0; i < nn && i < 10 && it != map.end(); ++i, ++it) + qCheckAccess(it.operator->()); + + QByteArray strippedInnerType = stripPointerType(d.innertype); + P(d, "numchild", nn); + P(d, "value", "<" << nn << " items>"); + P(d, "valuedisabled", "true"); + P(d, "valueoffset", d.extraInt[2]); + + if (d.dumpChildren) { + bool simpleKey = isSimpleType(keyType); + bool simpleValue = isShortKey(valueType); + int valueOffset = d.extraInt[2]; + + d << ",children=["; + std::map<int, int>::const_iterator it = map.begin(); + for (int i = 0; i < 1000 && it != map.end(); ++i, ++it) { + const void *node = it.operator->(); + if (simpleKey) { + d.beginHash(); + P(d, "type", valueType); + qDumpInnerValueHelper(d, keyType, node, "name"); + P(d, "nameisindex", "1"); + if (simpleValue) + qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset)); + P(d, "addr", addOffset(node, valueOffset)); + d.endHash(); + } else { + d.beginHash(); + P(d, "name", "[" << i << "]"); + P(d, "addr", it.operator->()); + P(d, "type", "std::pair<const " << keyType << "," << valueType << " >"); + d.endHash(); + } + } + if (it != map.end()) + d.putEllipsis(); + d << "]"; + } + d.disarm(); +} + static void qDumpStdString(QDumper &d) { const std::string &str = *reinterpret_cast<const std::string *>(d.data); @@ -2356,9 +2412,9 @@ static void handleProtocolVersion2and3(QDumper & d) qDumpStdVectorBool(d); else if (isEqual(type, "std::list")) qDumpStdList(d); - else if (isEqual(type, "string")) - qDumpStdString(d); - else if (isEqual(type, "std::string")) + else if (isEqual(type, "std::map")) + qDumpStdMap(d); + else if (isEqual(type, "std::string") || isEqual(type, "string")) qDumpStdString(d); else if (isEqual(type, "std::wstring")) qDumpStdWString(d); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 83473674782dd90e230b7cde2cfdbb2b487dbd15..5f7367b2e4ce0e8963373270175d42bdfbedbe3e 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -2941,6 +2941,8 @@ bool GdbEngine::isCustomValueDumperAvailable(const QString &type) const } if (tmplate == "std::list") return true; + if (tmplate == "std::map") + return true; if (tmplate == "std::vector" && inner != "bool") return true; if (tmplate == "std::basic_string") { @@ -2962,6 +2964,8 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) QStringList inners = inner.split('@'); if (inners.at(0).isEmpty()) inners.clear(); + for (int i = 0; i != inners.size(); ++i) + inners[i] = inners[i].simplified(); QString outertype = isTemplate ? tmplate : data.type; @@ -3015,6 +3019,12 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) //extraArgs[extraArgCount++] = sizeofTypeExpression(data.type); //extraArgs[extraArgCount++] = "(size_t)&(('" + data.type + "'*)0)->value"; } + } else if (outertype == "std::map") { + // We don't want the comparator and the allocator confuse gdb. + // But we need the offset of the second item in the value pair. + extraArgs[2] = "(size_t)&(('std::pair<const " + inners.at(0) + + "," + inners.at(1) + ">'*)0)->second"; + extraArgs[3] = "0"; } else if (outertype == "std::basic_string") { //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners; if (inners.at(0) == "char") { @@ -3064,6 +3074,8 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) + ',' + extraArgs[2] + ',' + extraArgs[3] + ')'; + //qDebug() << "CMD: " << cmd; + sendSynchronizedCommand(cmd, WatchDumpCustomValue1, QVariant::fromValue(data)); q->showStatusMessage( diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index ab5ee635b5afe67bf23a4e0aaf4f27385d73500a..1eea659625d086c87948907a71e50cff4db3b922 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -267,7 +267,7 @@ void testQMap() ggt[11] = QStringList() << "11"; ggt[22] = QStringList() << "22"; -#if 0 +#if 1 QMap<uint, float> gg0; gg0[11] = 11.0; gg0[22] = 22.0; @@ -413,16 +413,31 @@ void testStdList() void testStdMap() { + std::map<QString, Foo> gg3; + gg3["22.0"] = Foo(22); + gg3["33.0"] = Foo(33); + gg3["44.0"] = Foo(44); + +#if 1 + std::map<uint, uint> gg; + gg[11] = 1; + gg[22] = 2; + gg[33] = 3; + gg[44] = 4; + gg[55] = 5; + std::map<uint, QStringList> ggl; ggl[11] = QStringList() << "11"; ggl[22] = QStringList() << "22"; + ggl[33] = QStringList() << "33"; + ggl[44] = QStringList() << "44"; + ggl[55] = QStringList() << "55"; typedef std::map<uint, QStringList> T; T ggt; ggt[11] = QStringList() << "11"; ggt[22] = QStringList() << "22"; -#if 0 std::map<uint, float> gg0; gg0[11] = 11.0; gg0[22] = 22.0; @@ -434,15 +449,11 @@ void testStdMap() std::map<int, QString> gg2; gg2[22] = "22.0"; - std::map<QString, Foo> gg3; - gg3["22.0"] = Foo(22); - gg3["33.0"] = Foo(33); - QObject ob; std::map<QString, QPointer<QObject> > map; - map.insert("Hallo", QPointer<QObject>(&ob)); - map.insert("Welt", QPointer<QObject>(&ob)); - map.insert(".", QPointer<QObject>(&ob)); + map["Hallo"] = QPointer<QObject>(&ob); + map["Welt"] = QPointer<QObject>(&ob); + map["."] = QPointer<QObject>(&ob); #endif }