diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp
index 29b6feed765cbde9a846aeae741dd9bbf4135704..156bfc5e3f2ed03ad217c2ad2814f5987f689ca8 100644
--- a/share/qtcreator/gdbmacros/gdbmacros.cpp
+++ b/share/qtcreator/gdbmacros/gdbmacros.cpp
@@ -844,6 +844,26 @@ static void qDumpUnknown(QDumper &d, const char *why = 0)
     d.disarm();
 }
 
+static inline void dumpStdStringValue(QDumper &d, const std::string &str)
+{
+    d.beginItem("value");
+    d.putBase64Encoded(str.c_str(), str.size());
+    d.endItem();
+    d.putItem("valueencoded", "1");
+    d.putItem("type", "std::string");
+    d.putItem("numchild", "0");
+}
+
+static inline void dumpStdWStringValue(QDumper &d, const std::wstring &str)
+{
+    d.beginItem("value");
+    d.putBase64Encoded((const char *)str.c_str(), str.size() * sizeof(wchar_t));
+    d.endItem();
+    d.putItem("valueencoded", (sizeof(wchar_t) == 2 ? "2" : "3"));
+    d.putItem("type", "std::wstring");
+    d.putItem("numchild", "0");
+}
+
 static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr,
     const char *field = "value")
 {
@@ -928,6 +948,16 @@ static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr
                 d.putItem(field, *(QString*)addr);
             }
             return;
+        case 't':
+            if (isEqual(type, "std::string")
+                || isEqual(type, "std::basic_string<char,std::char_traits<char>,std::allocator<char> >")) {
+                d.putCommaIfNeeded();
+                dumpStdStringValue(d, *reinterpret_cast<const std::string*>(addr));
+            } else if (isEqual(type, "std::wstring")
+                       || isEqual(type, "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >")) {
+                dumpStdWStringValue(d, *reinterpret_cast<const std::wstring*>(addr));
+            }
+            return;
         default:
             return;
     }
@@ -944,7 +974,6 @@ static void qDumpInnerValue(QDumper &d, const char *type, const void *addr)
     qDumpInnerValueHelper(d, type, addr);
 }
 
-
 static void qDumpInnerValueOrPointer(QDumper &d,
     const char *type, const char *strippedtype, const void *addr)
 {
@@ -2753,37 +2782,28 @@ static void qDumpStdString(QDumper &d)
 {
     const std::string &str = *reinterpret_cast<const std::string *>(d.data);
 
-    if (!str.empty()) {
+    const std::string::size_type size = str.size();
+    if (int(size) < 0)
+        return;
+    if (size) {
         qCheckAccess(str.c_str());
-        qCheckAccess(str.c_str() + str.size() - 1);
+        qCheckAccess(str.c_str() + size - 1);
     }
-
-    d.beginItem("value");
-    d.putBase64Encoded(str.c_str(), str.size());
-    d.endItem();
-    d.putItem("valueencoded", "1");
-    d.putItem("type", "std::string");
-    d.putItem("numchild", "0");
-
+    dumpStdStringValue(d, str);
     d.disarm();
 }
 
 static void qDumpStdWString(QDumper &d)
 {
     const std::wstring &str = *reinterpret_cast<const std::wstring *>(d.data);
-
-    if (!str.empty()) {
+    const std::wstring::size_type size = str.size();
+    if (int(size) < 0)
+        return;
+    if (size) {
         qCheckAccess(str.c_str());
-        qCheckAccess(str.c_str() + str.size() - 1);
+        qCheckAccess(str.c_str() + size - 1);
     }
-
-    d.beginItem("value");
-    d.putBase64Encoded((const char *)str.c_str(), str.size() * sizeof(wchar_t));
-    d.endItem();
-    d.putItem("valueencoded", (sizeof(wchar_t) == 2 ? "2" : "3"));
-    d.putItem("type", "std::wstring");
-    d.putItem("numchild", "0");
-
+    dumpStdWStringValue(d, str);
     d.disarm();
 }
 
@@ -3164,6 +3184,8 @@ void *qDumpObjectData440(
          .put("std::string=\"").put(sizeof(std::string)).put("\",")
          .put("std::wstring=\"").put(sizeof(std::wstring)).put("\",")
          .put("std::allocator=\"").put(sizeof(std::allocator<int>)).put("\",")
+         .put("std::char_traits<char>=\"").put(sizeof(std::char_traits<char>)).put("\",")
+         .put("std::char_traits<unsigned short>=\"").put(sizeof(std::char_traits<unsigned short>)).put("\",")
 #if QT_VERSION >= 0x040500
          .put(NS"QSharedPointer=\"").put(sizeof(QSharedPointer<int>)).put("\",")
          .put(NS"QSharedDataPointer=\"").put(sizeof(QSharedDataPointer<QSharedData>)).put("\",")
diff --git a/share/qtcreator/gdbmacros/test/main.cpp b/share/qtcreator/gdbmacros/test/main.cpp
index fe6c2c6723eebd142c3b812f49bcccaac5cbd72e..eca00156df3ecf9f10b1e1e5c170d9a32389cef6 100644
--- a/share/qtcreator/gdbmacros/test/main.cpp
+++ b/share/qtcreator/gdbmacros/test/main.cpp
@@ -256,6 +256,18 @@ static int dumpStdStringVector()
     return 0;
 }
 
+static int dumpStdWStringVector()
+{
+    std::vector<std::wstring> test;
+    test.push_back(L"item1");
+    test.push_back(L"item2");
+    prepareInBuffer("std::vector", "local.wstringvector", "local.wstringvector", "std::wstring");
+    qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::wstring), sizeof(std::list<int>::allocator_type), 0, 0);
+    fputs(qDumpOutBuffer, stdout);
+    fputc('\n', stdout);
+    return 0;
+}
+
 static int dumpStdIntSet()
 {
     std::set<int> test;
@@ -335,6 +347,8 @@ static bool dumpType(const char *arg)
         { dumpStdIntVector(); return true; }
     if (!qstrcmp(arg, "vector<string>"))
         { dumpStdStringVector(); return true; }
+    if (!qstrcmp(arg, "vector<wstring>"))
+        { dumpStdWStringVector(); return true; }
     if (!qstrcmp(arg, "set<int>"))
         { dumpStdIntSet(); return true; }
     if (!qstrcmp(arg, "set<string>"))
diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
index 0209a08e2b479df8a9df9f5ee66befe7f5a787e4..bedf02dd41e0368f1e40c032471c391097883c8c 100644
--- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp
+++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
@@ -544,12 +544,23 @@ static inline QString msgDumpFailed(const WatchData &wd, const QString *why)
     return QString::fromLatin1("Unable to dump '%1' (%2): %3").arg(wd.name, wd.type, *why);
 }
 
+static inline QString msgNotHandled(const QString &type)
+{
+    return QString::fromLatin1("The type '%1' is not handled.").arg(type);
+}
+
 CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool dumpChildren, int source,
                                                       QList<WatchData> *result, QString *errorMessage)
 {
     // Check failure cache and supported types
-    if (m_state == Disabled || m_failedTypes.contains(wd.type))
+    if (m_state == Disabled) {
+        *errorMessage = QLatin1String("Dumpers are disabled");
         return DumpNotHandled;
+    }
+    if (m_failedTypes.contains(wd.type)) {
+        *errorMessage = msgNotHandled(wd.type);
+        return DumpNotHandled;
+    }
 
     // Ensure types are parsed and known.
     if (!ensureInitialized(errorMessage)) {
@@ -562,8 +573,10 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
     const QtDumperHelper::TypeData td = m_helper.typeData(wd.type);    
     if (loadDebug)
         qDebug() << "dumpType" << wd.type << td;
-    if (td.type == QtDumperHelper::UnknownType)
+    if (td.type == QtDumperHelper::UnknownType) {
+        *errorMessage = msgNotHandled(wd.type);
         return DumpNotHandled;
+    }
 
     // Now evaluate
     const QString message = QCoreApplication::translate("Debugger::Internal::CdbDumperHelper",
diff --git a/src/plugins/debugger/cdb/cdbstackframecontext.cpp b/src/plugins/debugger/cdb/cdbstackframecontext.cpp
index 9cd7589636e031473725e619439aae54ae12eddb..870ba8f262f2fc4b42ba897e568f7fbc2ecb4cb0 100644
--- a/src/plugins/debugger/cdb/cdbstackframecontext.cpp
+++ b/src/plugins/debugger/cdb/cdbstackframecontext.cpp
@@ -257,7 +257,7 @@ bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal,
             foreach(const WatchData &dwd, dumperResult)
                 wh->insertData(dwd);
         } else {
-            const QString msg = QString::fromLatin1("Unable to further expand dumper watch data: %1 (%2): %3/%4").arg(incompleteLocal.name, incompleteLocal.type).arg(int(dr)).arg(*errorMessage);
+            const QString msg = QString::fromLatin1("Unable to further expand dumper watch data: '%1' (%2): %3/%4").arg(incompleteLocal.name, incompleteLocal.type).arg(int(dr)).arg(*errorMessage);
             qWarning("%s", qPrintable(msg));
             WatchData wd = incompleteLocal;
             wd.setAllUnneeded();
diff --git a/src/plugins/debugger/debuggertooltip.cpp b/src/plugins/debugger/debuggertooltip.cpp
index 18fa2f7d6f1695d6e903052b34e3bd5fa7bb9a4d..622a8948e872f436d318902503bbfcd1bff757ec 100644
--- a/src/plugins/debugger/debuggertooltip.cpp
+++ b/src/plugins/debugger/debuggertooltip.cpp
@@ -144,7 +144,7 @@ void ToolTipWidget::done()
 }
 
 void ToolTipWidget::run(const QPoint &point, QAbstractItemModel *model,
-    const QModelIndex &index, const QString &msg)
+    const QModelIndex &index, const QString & /* msg */)
 {
     move(point);
     setModel(model);
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index c37938af49278b4a974fe445457153bd43a98443..30eb77478b0ea7cec227020968d26fe9d698d2ed 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -390,9 +390,29 @@ static QString chopConst(QString type)
     return type;
 }
 
-QString niceType(QString type)
-{
-    type.replace('*', '@');
+static inline QRegExp stdStringRegExp(const QString &charType)
+{
+    QString rc = QLatin1String("basic_string<");
+    rc += charType;
+    rc += QLatin1String(",[ ]?std::char_traits<");
+    rc += charType;
+    rc += QLatin1String(">,[ ]?std::allocator<");
+    rc += charType;
+    rc += QLatin1String("> >");
+    const QRegExp re(rc);
+    Q_ASSERT(re.isValid());
+    return re;
+}
+
+QString niceType(const QString typeIn)
+{
+    static QMap<QString, QString> cache;
+    const QMap<QString, QString>::const_iterator it = cache.constFind(typeIn);
+    if (it != cache.constEnd()) {
+        return it.value();
+    }
+    QString type = typeIn;
+    type.replace(QLatin1Char('*'), QLatin1Char('@'));
 
     for (int i = 0; i < 10; ++i) {
         int start = type.indexOf("std::allocator<");
@@ -414,33 +434,37 @@ QString niceType(QString type)
         QString alloc = type.mid(start, pos + 1 - start).trimmed();
         QString inner = alloc.mid(15, alloc.size() - 16).trimmed();
 
-        if (inner == QLatin1String("char"))
-            // std::string
-            type.replace(QLatin1String("basic_string<char, std::char_traits<char>, "
-                "std::allocator<char> >"), QLatin1String("string"));
-        else if (inner == QLatin1String("wchar_t"))
-            // std::wstring
-            type.replace(QLatin1String("basic_string<wchar_t, std::char_traits<wchar_t>, "
-                "std::allocator<wchar_t> >"), QLatin1String("wstring"));
-
+        if (inner == QLatin1String("char")) { // std::string
+            static const QRegExp stringRegexp = stdStringRegExp(inner);
+            type.replace(stringRegexp, QLatin1String("string"));
+        } else if (inner == QLatin1String("wchar_t")) { // std::wstring
+            static const QRegExp wchartStringRegexp = stdStringRegExp(inner);
+            type.replace(wchartStringRegexp, QLatin1String("wstring"));
+        } else if (inner == QLatin1String("unsigned short")) { // std::wstring/MSVC
+            static const QRegExp usStringRegexp = stdStringRegExp(inner);
+            type.replace(usStringRegexp, QLatin1String("wstring"));
+        }
         // std::vector, std::deque, std::list
-        QRegExp re1(QString("(vector|list|deque)<%1, %2\\s*>").arg(inner, alloc));
+        static const QRegExp re1(QString::fromLatin1("(vector|list|deque)<%1,[ ]?%2\\s*>").arg(inner, alloc));
+        Q_ASSERT(re1.isValid());
         if (re1.indexIn(type) != -1)
-            type.replace(re1.cap(0), QString("%1<%2>").arg(re1.cap(1), inner));
-
+            type.replace(re1.cap(0), QString::fromLatin1("%1<%2>").arg(re1.cap(1), inner));
 
         // std::stack
-        QRegExp re6(QString("stack<%1, std::deque<%2> >").arg(inner, inner));
-        re6.setMinimal(true);
+        static QRegExp re6(QString::fromLatin1("stack<%1,[ ]?std::deque<%2> >").arg(inner, inner));
+        if (!re6.isMinimal())
+            re6.setMinimal(true);
+        Q_ASSERT(re6.isValid());
         if (re6.indexIn(type) != -1)
-            type.replace(re6.cap(0), QString("stack<%1>").arg(inner));
+            type.replace(re6.cap(0), QString::fromLatin1("stack<%1>").arg(inner));
 
         // std::set
-        QRegExp re4(QString("set<%1, std::less<%2>, %3\\s*>").arg(inner, inner, alloc));
-        re4.setMinimal(true);
+        static QRegExp re4(QString::fromLatin1("set<%1,[ ]?std::less<%2>,[ ]?%3\\s*>").arg(inner, inner, alloc));
+        if (!re4.isMinimal())
+            re4.setMinimal(true);
+        Q_ASSERT(re4.isValid());
         if (re4.indexIn(type) != -1)
-            type.replace(re4.cap(0), QString("set<%1>").arg(inner));
-
+            type.replace(re4.cap(0), QString::fromLatin1("set<%1>").arg(inner));
 
         // std::map
         if (inner.startsWith("std::pair<")) {
@@ -460,22 +484,26 @@ QString niceType(QString type)
             QString key = chopConst(ckey);
             QString value = inner.mid(pos + 2, inner.size() - 3 - pos);
 
-            QRegExp re5(QString("map<%1, %2, std::less<%3>, %4\\s*>")
+            static QRegExp re5(QString("map<%1,[ ]?%2,[ ]?std::less<%3>,[ ]?%4\\s*>")
                 .arg(key, value, key, alloc));
-            re5.setMinimal(true);
+            if (!re5.isMinimal())
+                re5.setMinimal(true);
+            Q_ASSERT(re5.isValid());
             if (re5.indexIn(type) != -1)
                 type.replace(re5.cap(0), QString("map<%1, %2>").arg(key, value));
             else {
-                QRegExp re7(QString("map<const %1, %2, std::less<const %3>, %4\\s*>")
+                static QRegExp re7(QString("map<const %1,[ ]?%2,[ ]?std::less<const %3>,[ ]?%4\\s*>")
                     .arg(key, value, key, alloc));
-                re7.setMinimal(true);
+                if (!re7.isMinimal())
+                    re7.setMinimal(true);
                 if (re7.indexIn(type) != -1)
                     type.replace(re7.cap(0), QString("map<const %1, %2>").arg(key, value));
             }
         }
     }
-    type.replace('@', '*');
+    type.replace(QLatin1Char('@'), QLatin1Char('*'));
     type.replace(QLatin1String(" >"), QString(QLatin1Char('>')));
+    cache.insert(typeIn, type); // For simplicity, also cache unmodified types
     return type;
 }
 
diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp
index 0263ca51a832693949678c0cc1d6b54a68b3741f..5ef9523ed4535fba43d55b7af9f1db97270542f6 100644
--- a/src/plugins/debugger/watchutils.cpp
+++ b/src/plugins/debugger/watchutils.cpp
@@ -266,30 +266,43 @@ bool extractTemplate(const QString &type, QString *tmplate, QString *inner)
     // Input "Template<Inner1,Inner2,...>::Foo" will return "Template::Foo" in
     // 'tmplate' and "Inner1@Inner2@..." etc in 'inner'. Result indicates
     // whether parsing was successful
+    // Gdb inserts a blank after each comma which we would like to avoid
+    tmplate->clear();
+    inner->clear();
+    if (!type.contains(QLatin1Char('<')))
+        return  false;
     int level = 0;
     bool skipSpace = false;
+    const int size = type.size();
 
-    for (int i = 0; i != type.size(); ++i) {
+    for (int i = 0; i != size; ++i) {
         const QChar c = type.at(i);
-        if (c == QLatin1Char(' ') && skipSpace) {
-            skipSpace = false;
-        } else if (c == QLatin1Char('<')) {
+        const char asciiChar = c.toAscii();
+        switch (asciiChar) {
+        case '<':
             *(level == 0 ? tmplate : inner) += c;
             ++level;
-        } else if (c == QLatin1Char('>')) {
+            break;
+        case '>':
             --level;
             *(level == 0 ? tmplate : inner) += c;
-        } else if (c == QLatin1Char(',')) {
+            break;
+        case ',':
             *inner += (level == 1) ? QLatin1Char('@') : QLatin1Char(',');
             skipSpace = true;
-        } else {
-            *(level == 0 ? tmplate : inner) += c;
+            break;
+        default:
+            if (!skipSpace || asciiChar != ' ') {
+                *(level == 0 ? tmplate : inner) += c;
+                skipSpace = false;
+            }
+            break;
         }
     }
     *tmplate = tmplate->trimmed();
     *tmplate = tmplate->remove(QLatin1String("<>"));
     *inner = inner->trimmed();
-    //qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type;
+    // qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type;
     return !inner->isEmpty();
 }
 
@@ -408,7 +421,7 @@ bool isCppEditor(Core::IEditor *editor)
 // Find the function the cursor is in to use a scope.
 
 
-    
+
 
 
 // Return the Cpp expression, and, if desired, the function
@@ -442,7 +455,7 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
         const QTextCursor tc = plaintext->textCursor();
         *column = tc.columnNumber();
         *line = tc.blockNumber();
-    }    
+    }
 
     if (function && !expr.isEmpty())
         if (const Core::IFile *file = editor->file())
@@ -455,6 +468,7 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
 // --------------- QtDumperResult
 
 QtDumperResult::Child::Child() :
+   keyEncoded(0),
    valueEncoded(0),
    childCount(0),
    valuedisabled(false)
@@ -475,6 +489,7 @@ void QtDumperResult::clear()
     value.clear();
     address.clear();
     type.clear();
+    extra.clear();
     displayedType.clear();
     valueEncoded = 0;
     valuedisabled = false;
@@ -509,8 +524,17 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
                 wchild.source = source;
                 wchild.iname = iname;
                 wchild.iname += dot;
-                wchild.iname += dchild.name;                
-                wchild.name = dchild.name;
+                wchild.iname += dchild.name;
+                // Use key entry as name (which is used for map nodes)
+                if (dchild.key.isEmpty()) {
+                    wchild.name = dchild.name;
+                } else {
+                    wchild.name = decodeData(dchild.key, dchild.keyEncoded);
+                    if (wchild.name.size() > 13) {
+                        wchild.name.truncate(12);
+                        wchild.name += QLatin1String("...");
+                    }
+                }
                 wchild.exp = dchild.exp;
                 wchild.valuedisabled = dchild.valuedisabled;
                 wchild.setType(dchild.type.isEmpty() ? childType : dchild.type);
@@ -533,18 +557,21 @@ QDebug operator<<(QDebug in, const QtDumperResult &d)
             << " address=" << d.address
             << " value="  << d.value
             << " disabled=" << d.valuedisabled
-            << " encoded=" << d.valueEncoded << " internal=" << d.internal;
+            << " encoded=" << d.valueEncoded << " internal=" << d.internal
+            << " extra='" << d.extra << "'\n";
     const int realChildCount = d.children.size();
     if (d.childCount || realChildCount) {
-        nospace << " childCount=" << d.childCount << '/' << realChildCount
+        nospace << "childCount=" << d.childCount << '/' << realChildCount
                 << " childType=" << d.childType << '\n';
         for (int i = 0; i < realChildCount; i++) {
             const QtDumperResult::Child &c = d.children.at(i);
             nospace << "   #" << i << " addr=" << c.address
                     << " disabled=" << c.valuedisabled
                     << " type=" << c.type << " exp=" << c.exp
-                    << " name=" << c.name << " encoded=" << c.valueEncoded
-                    << " value=" << c.value
+                    << " name=" << c.name;
+            if (!c.key.isEmpty())
+                nospace << " keyencoded=" << c.keyEncoded << " key=" << c.key;
+            nospace << " valueencoded=" << c.valueEncoded << " value=" << c.value
                     << "childcount=" << c.childCount << '\n';
         }
     }
@@ -770,6 +797,7 @@ class DumperParser
 public:
     explicit DumperParser(const char *s) : m_s(s) {}
     bool run();
+    virtual ~DumperParser() {}
 
 protected:
     // handle 'key="value"'
@@ -833,9 +861,9 @@ bool DumperParser::parseHash(int level, const char *&pos)
             return false;
         pos = equalsPtr + 1;
         if (!*pos)
-            return false;        
+            return false;
         if (!parseValue(level + 1, pos))
-            return false;    
+            return false;
         if (*pos == ',')
             pos++;
     }
@@ -871,7 +899,7 @@ bool DumperParser::parseValue(int level, const char *&pos)
                 if (*pos == ',')
                     pos++;
             }
-        }        
+        }
         return false;
         // A hash '{a="b",b="c"}'
     case '{': {
@@ -879,7 +907,7 @@ bool DumperParser::parseValue(int level, const char *&pos)
                 return false;
             pos++;
             if (!parseHash(level + 1, pos))
-                return false;            
+                return false;
             return handleHashEnd();
         }
         return false;
@@ -952,7 +980,7 @@ public:
 
 protected:
     virtual bool handleKeyword(const char *k, int size);
-    virtual bool handleListStart();    
+    virtual bool handleListStart();
     virtual bool handleListEnd();
     virtual bool handleHashEnd();
     virtual bool handleValue(const char *k, int size);
@@ -972,7 +1000,7 @@ QueryDumperParser::QueryDumperParser(const char *s) :
 {
 }
 
-bool QueryDumperParser::handleKeyword(const char *k, int size)        
+bool QueryDumperParser::handleKeyword(const char *k, int size)
 {
     switch (m_mode) {
     case ExpectingSizes:
@@ -1064,7 +1092,6 @@ bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
     foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes)
         addSize(se.first, se.second);
     m_expressionCache = parser.data().expressionCache;
-    qDebug() << m_expressionCache;
     return true;
 }
 
@@ -1081,13 +1108,15 @@ void QtDumperHelper::addSize(const QString &name, int size)
         return;
     }
     do {
+        // CDB helpers
         if (name == QLatin1String("std::string")) {
-            m_sizeCache.insert(QLatin1String("std::basic_string<char,std::char_traits<char>,std::allocator<char>>"), size);
+            m_sizeCache.insert(QLatin1String("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"), size);
+            m_sizeCache.insert(QLatin1String("basic_string<char,char_traits<char>,allocator<char> >"), size);
             break;
         }
         if (name == QLatin1String("std::wstring")) {
-            // FIXME: check space between > > below?
-            m_sizeCache.insert(QLatin1String("std::basic_string<unsigned short,std::char_traits<unsignedshort>,std::allocator<unsignedshort> >"), size);
+            m_sizeCache.insert(QLatin1String("basic_string<unsigned short,char_traits<unsignedshort>,allocator<unsignedshort> >"), size);
+            m_sizeCache.insert(QLatin1String("std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >"), size);
             break;
         }
     } while (false);
@@ -1297,10 +1326,16 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
             // But we need the offset of the second item in the value pair.
             // We read the type of the pair from the allocator argument because
             // that gets the constness "right" (in the sense that gdb can
-            // read it back;
+            // read it back: "std::allocator<std::pair<Key,Value> >"
+            // -> "std::pair<Key,Value>". Different debuggers have varying
+            // amounts of terminating blanks...
             QString pairType = inners.at(3);
-            // remove 'std::allocator<...>':
-            pairType = pairType.mid(15, pairType.size() - 15 - 2);
+            int bracketPos = pairType.indexOf(QLatin1Char('<'));
+            if (bracketPos != -1)
+                pairType.remove(0, bracketPos + 1);
+            bracketPos = pairType.indexOf(QLatin1Char('>'));
+            if (bracketPos != -1)
+                pairType.truncate(bracketPos + 1);
             extraArgs[2] = QLatin1String("(size_t)&(('");
             extraArgs[2] += pairType;
             extraArgs[2] += QLatin1String("'*)0)->second");
@@ -1377,12 +1412,15 @@ private:
                 ExpectingType, ExpectingDisplayedType, ExpectingInternal,
                 ExpectingValueDisabled,  ExpectingValueEncoded,
                 ExpectingCommonChildType, ExpectingChildCount,
+                ExpectingExtra,
                 IgnoreNext,
                 ChildModeStart,
                 ExpectingChildren,ExpectingChildName, ExpectingChildAddress,
                 ExpectingChildExpression, ExpectingChildType,
+                ExpectingChildKey, ExpectingChildKeyEncoded,
                 ExpectingChildValue, ExpectingChildValueEncoded,
-                ExpectingChildValueDisabled, ExpectingChildChildCount
+                ExpectingChildValueDisabled, ExpectingChildChildCount,
+                IgnoreNextChildMode
               };
 
     static inline Mode nextMode(Mode in, const char *keyword, int size);
@@ -1405,6 +1443,8 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
     case 3:
         if (!qstrncmp(keyword, "exp", size))
             return ExpectingChildExpression;
+        if (!qstrncmp(keyword, "key", size))
+            return ExpectingChildKey;
         break;
     case 4:
         if (!qstrncmp(keyword, "addr", size))
@@ -1419,6 +1459,8 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
             return ExpectingIName;
         if (!qstrncmp(keyword, "value", size))
             return in > ChildModeStart ? ExpectingChildValue : ExpectingValue;
+        if (!qstrncmp(keyword, "extra", size))
+            return ExpectingExtra;
         break;
     case 8:
         if (!qstrncmp(keyword, "children", size))
@@ -1431,7 +1473,11 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
     case 9:
         if (!qstrncmp(keyword, "childtype", size))
             return ExpectingCommonChildType;
-        break;    
+        break;
+    case 10:
+        if (!qstrncmp(keyword, "keyencoded", size))
+            return ExpectingChildKeyEncoded;
+        break;
     case 12:
         if (!qstrncmp(keyword, "valueencoded", size))
             return in > ChildModeStart ? ExpectingChildValueEncoded : ExpectingValueEncoded;
@@ -1442,10 +1488,10 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
         if (!qstrncmp(keyword, "displayedtype", size))
             return ExpectingDisplayedType;
         if (!qstrncmp(keyword, "childnumchild", size))
-            return IgnoreNext;
+            return IgnoreNextChildMode;
         break;
     }
-    return IgnoreNext;
+    return in > ChildModeStart ? IgnoreNextChildMode : IgnoreNext;
 }
 
 bool ValueDumperParser::handleKeyword(const char *k, int size)
@@ -1491,6 +1537,9 @@ bool ValueDumperParser::handleValue(const char *k, int size)
     case ExpectingDisplayedType:
         m_result.displayedType = QString::fromLatin1(valueBA);
         break;
+    case ExpectingExtra:
+        m_result.extra = valueBA;
+        break;
     case ExpectingInternal:
         m_result.internal = valueBA == "true";
         break;
@@ -1501,6 +1550,7 @@ bool ValueDumperParser::handleValue(const char *k, int size)
         m_result.childCount = QString::fromLatin1(valueBA).toInt();
         break;
     case ExpectingChildren:
+    case IgnoreNextChildMode:
     case IgnoreNext:
         break;
     case ExpectingChildName:
@@ -1509,6 +1559,12 @@ bool ValueDumperParser::handleValue(const char *k, int size)
     case ExpectingChildAddress:
         m_result.children.back().address = QString::fromLatin1(valueBA);
         break;
+    case ExpectingChildKeyEncoded:
+        m_result.children.back().keyEncoded = QString::fromLatin1(valueBA).toInt();
+        break;
+    case ExpectingChildKey:
+        m_result.children.back().key = valueBA;
+        break;
     case ExpectingChildValue:
         m_result.children.back().value = valueBA;
         break;
@@ -1532,7 +1588,7 @@ bool ValueDumperParser::handleValue(const char *k, int size)
 }
 
 bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r)
-{    
+{
     ValueDumperParser parser(data);
     if (!parser.run())
         return false;
@@ -1541,7 +1597,7 @@ bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r)
     if (r->childCount < r->children.size())
         r->childCount  = r->children.size();
     if (debug)
-        qDebug() << '\n' << data << *r;
+        qDebug() << '\n' << data << '\n' << *r;
     return true;
 }
 
diff --git a/src/plugins/debugger/watchutils.h b/src/plugins/debugger/watchutils.h
index 94948499e7bc2e7083b83e9523a1952663d6988e..9d39372aa0e8588fd3c56ccf50024c0e94a99269 100644
--- a/src/plugins/debugger/watchutils.h
+++ b/src/plugins/debugger/watchutils.h
@@ -90,13 +90,15 @@ struct QtDumperResult
     struct Child {
         Child();
 
-        int valueEncoded;
+        int keyEncoded;
+        int valueEncoded;        
         int childCount;
         bool valuedisabled;
         QString name;
         QString address;
         QString exp;
         QString type;
+        QByteArray key;
         QByteArray value;
     };
 
@@ -107,6 +109,7 @@ struct QtDumperResult
     QString iname;
     QString address;
     QString type;
+    QString extra;
     QString displayedType;
     QByteArray value;
     int valueEncoded;