diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp
index 5f039321de4045922534ecd47174ed04cb034abe..dcd016495a64194906bbe254d17ee3751f6e5506 100644
--- a/share/qtcreator/gdbmacros/gdbmacros.cpp
+++ b/share/qtcreator/gdbmacros/gdbmacros.cpp
@@ -174,6 +174,9 @@ QT_BEGIN_NAMESPACE
 
 struct Sender { QObject *sender; int signal; int ref; };
 
+const char *stdStringTypeC = "std::basic_string<char,std::char_traits<char>,std::allocator<char> >";
+const char *stdWideStringTypeUShortC = "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >";
+
 #if QT_VERSION < 0x040600
     struct Connection
     {
@@ -905,7 +908,8 @@ static inline void dumpChildNumChildren(QDumper &d, InnerValueResult innerValueR
     }
 }
 
-static InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr,
+// Called by templates, so, not static.
+InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr,
     const char *field = "value")
 {
     char buf[30];
@@ -1017,13 +1021,13 @@ static InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, cons
             return InnerValueNotHandled;
         case 't':
             if (isEqual(type, "std::string")
-                || isEqual(type, "std::basic_string<char,std::char_traits<char>,std::allocator<char> >")) {
+                || isEqual(type, stdStringTypeC)) {
                 d.putCommaIfNeeded();
                 dumpStdStringValue(d, *reinterpret_cast<const std::string*>(addr));
                 return InnerValueNoFurtherChildren;
             }
             if (isEqual(type, "std::wstring")
-                || isEqual(type, "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >")) {
+                || isEqual(type, stdWideStringTypeUShortC)) {
                 dumpStdWStringValue(d, *reinterpret_cast<const std::wstring*>(addr));
                 return InnerValueNoFurtherChildren;
             }
@@ -2905,9 +2909,16 @@ static void qDumpStdList(QDumper &d)
     d.disarm();
 }
 
-static void qDumpStdMap(QDumper &d)
+/* Dump out an arbitrary map. To iterate the map,
+ * it is cast to a map of <KeyType,Value>. 'int' can be used for both
+ * for all types if the implementation does not depend on the types
+ * which is the case for GNU STL. The implementation used by MS VC, however,
+ * does depend on the key/value type, so, special cases need to be hardcoded. */
+
+template <class KeyType, class ValueType>
+static void qDumpStdMapHelper(QDumper &d)
 {
-    typedef std::map<int, int> DummyType;
+    typedef std::map<KeyType, ValueType> DummyType;
     const DummyType &map = *reinterpret_cast<const DummyType*>(d.data);
     const char *keyType   = d.templateParameters[0];
     const char *valueType = d.templateParameters[1];
@@ -2915,14 +2926,15 @@ static void qDumpStdMap(QDumper &d)
     qCheckAccess(p);
     p = deref(p);
 
-    int nn = map.size();
+    const int nn = map.size();
     if (nn < 0)
         return;
-    DummyType::const_iterator it = map.begin();
-    for (int i = 0; i < nn && i < 10 && it != map.end(); ++i, ++it)
+    Q_TYPENAME DummyType::const_iterator it = map.begin();
+    const Q_TYPENAME DummyType::const_iterator cend = map.end();
+    for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)
         qCheckAccess(it.operator->());
 
-    QByteArray strippedInnerType = stripPointerType(d.innertype);
+    const QByteArray strippedInnerType = stripPointerType(d.innertype);
     d.putItem("numchild", nn);
     d.putItemCount("value", nn);
     d.putItem("valuedisabled", "true");
@@ -2937,6 +2949,7 @@ static void qDumpStdMap(QDumper &d)
     pairType[strlen(pairType) - 2] = 0;
     d.putItem("pairtype", pairType);
 
+    InnerValueResult innerValueResult = InnerValueChildrenSpecified;
     if (d.dumpChildren) {
         bool isSimpleKey = isSimpleType(keyType);
         bool isSimpleValue = isSimpleType(valueType);
@@ -2951,12 +2964,12 @@ static void qDumpStdMap(QDumper &d)
 
         d.beginChildren();
         it = map.begin();
-        for (int i = 0; i < 1000 && it != map.end(); ++i, ++it) {
+        for (int i = 0; i < 1000 && it != cend; ++i, ++it) {
             d.beginHash();
                 const void *node = it.operator->();
                 d.putItem("name", i);
                 qDumpInnerValueHelper(d, keyType, node, "key");
-                qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset));
+                innerValueResult = qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset));
                 if (isSimpleKey && isSimpleValue) {
                     d.putItem("type", valueType);
                     d.putItem("addr", addOffset(node, valueOffset));
@@ -2972,22 +2985,61 @@ static void qDumpStdMap(QDumper &d)
             d.putEllipsis();
         d.endChildren();
     }
+    dumpChildNumChildren(d, innerValueResult);
     d.disarm();
 }
 
-static void qDumpStdSet(QDumper &d)
+static void qDumpStdMap(QDumper &d)
+{
+#ifdef Q_CC_MSVC
+    // As the map implementation inherits from a base class
+    // depending on the key, use something equivalent to iterate it.
+    const int keySize = d.extraInt[0];
+    const int valueSize = d.extraInt[1];
+    if (keySize == valueSize) {
+        if (keySize == sizeof(int)) {
+            qDumpStdMapHelper<int,int>(d);
+            return;
+        }
+        if (keySize == sizeof(std::string)) {
+            qDumpStdMapHelper<std::string,std::string>(d);
+            return;
+        }
+        return;
+    }
+    if (keySize == sizeof(int) && valueSize == sizeof(std::string)) {
+        qDumpStdMapHelper<int,std::string>(d);
+        return;
+    }
+    if (keySize == sizeof(std::string) && valueSize == sizeof(int)) {
+        qDumpStdMapHelper<std::string,int>(d);
+        return;
+    }
+#else
+    qDumpStdMapHelper<int,int>(d);
+#endif
+}
+
+/* Dump out an arbitrary set. To iterate the set,
+ * it is cast to a set of <KeyType>. 'int' can be used
+ * for all types if the implementation does not depend on the key type
+ * which is the case for GNU STL. The implementation used by MS VC, however,
+ * does depend on the key type, so, special cases need to be hardcoded. */
+
+template <class KeyType>
+static void qDumpStdSetHelper(QDumper &d)
 {
-    typedef std::set<int> DummyType;
+    typedef std::set<KeyType> DummyType;
     const DummyType &set = *reinterpret_cast<const DummyType*>(d.data);
     const void *p = d.data;
     qCheckAccess(p);
     p = deref(p);
 
-    int nn = set.size();
+    const int nn = set.size();
     if (nn < 0)
         return;
-    DummyType::const_iterator it = set.begin();
-    const DummyType::const_iterator cend = set.end();
+    Q_TYPENAME DummyType::const_iterator it = set.begin();
+    const Q_TYPENAME DummyType::const_iterator cend = set.end();
     for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)
         qCheckAccess(it.operator->());
 
@@ -3024,6 +3076,29 @@ static void qDumpStdSet(QDumper &d)
     d.disarm();
 }
 
+static void qDumpStdSet(QDumper &d)
+{
+#ifdef Q_CC_MSVC
+    // As the set implementation inherits from a base class
+    // depending on the key, use something equivalent to iterate it.
+    const int innerSize = d.extraInt[0];
+    if (innerSize == sizeof(int)) {
+        qDumpStdSetHelper<int>(d);
+        return;
+    }
+    if (innerSize == sizeof(std::string)) {
+        qDumpStdSetHelper<std::string>(d);
+        return;
+    }
+    if (innerSize == sizeof(std::wstring)) {
+        qDumpStdSetHelper<std::wstring>(d);
+        return;
+    }
+#else
+    qDumpStdSetHelper<int>(d);
+#endif
+}
+
 static void qDumpStdString(QDumper &d)
 {
     const std::string &str = *reinterpret_cast<const std::string *>(d.data);
@@ -3329,12 +3404,37 @@ template <class Key, class Value>
     d.put(keyType);
     d.put(',');
     d.put(valueType);
+    if (valueType[qstrlen(valueType) - 1] == '>')
+        d.put(' ');
     d.put(">'*)0)->value=\"");
     d.put(valueOffset);
     d.put('"');
     return d;
 }
 
+// Helper to write out common expression values for CDB:
+// Offsets of a std::pair for dumping std::map node value which look like
+// "(size_t)&(('std::pair<int const ,unsigned int>'*)0)->second"
+
+template <class Key, class Value>
+        inline QDumper & putStdPairValueOffsetExpression(const char *keyType,
+                                                         const char *valueType,
+                                                         QDumper &d)
+{
+    std::pair<Key, Value> *p = 0;
+    const int valueOffset = (char *)&(p->second) - (char*)p;
+    d.put("(size_t)&(('std::pair<");
+    d.put(keyType);
+    d.put(" const ,");
+    d.put(valueType);
+    if (valueType[qstrlen(valueType) - 1] == '>')
+        d.put(' ');
+    d.put(">'*)0)->second=\"");
+    d.put(valueOffset);
+    d.put('"');
+    return  d;
+}
+
 extern "C" Q_DECL_EXPORT
 void *qDumpObjectData440(
     int protocolVersion,
@@ -3461,7 +3561,18 @@ void *qDumpObjectData440(
         putQMapNodeOffsetExpression<int,QVariant>("int", NS"QVariant", d).put(',');
         putQMapNodeOffsetExpression<QString,int>(NS"QString", "int", d).put(',');
         putQMapNodeOffsetExpression<QString,QString>(NS"QString", NS"QString", d).put(',');
-        putQMapNodeOffsetExpression<QString,QVariant>(NS"QString", NS"QVariant", d);
+        putQMapNodeOffsetExpression<QString,QVariant>(NS"QString", NS"QVariant", d).put(',');
+        // Std Pairs
+        putStdPairValueOffsetExpression<int,int>("int","int", d).put(',');
+        putStdPairValueOffsetExpression<QString,QString>(NS"QString",NS"QString", d).put(',');
+        putStdPairValueOffsetExpression<int,QString>("int",NS"QString", d).put(',');
+        putStdPairValueOffsetExpression<QString,int>(NS"QString", "int", d).put(',');
+        putStdPairValueOffsetExpression<std::string,std::string>(stdStringTypeC, stdStringTypeC, d).put(',');
+        putStdPairValueOffsetExpression<int,std::string>("int", stdStringTypeC, d).put(',');
+        putStdPairValueOffsetExpression<std::string,int>(stdStringTypeC, "int", d.put(','));
+        putStdPairValueOffsetExpression<std::wstring,std::wstring>(stdWideStringTypeUShortC, stdWideStringTypeUShortC, d).put(',');
+        putStdPairValueOffsetExpression<int,std::wstring>("int", stdWideStringTypeUShortC, d).put(',');
+        putStdPairValueOffsetExpression<std::wstring,int>(stdWideStringTypeUShortC, "int", d);
         d.put('}');
         d.disarm();
     }
diff --git a/share/qtcreator/gdbmacros/test/main.cpp b/share/qtcreator/gdbmacros/test/main.cpp
index 0ec31578b0e6b82d03fcb6758807d270ee9bb005..8b24d55aca60fbfe7c081c8ea84f9f3e84a2d6b8 100644
--- a/share/qtcreator/gdbmacros/test/main.cpp
+++ b/share/qtcreator/gdbmacros/test/main.cpp
@@ -308,6 +308,18 @@ static int dumpStdStringSet()
     return 0;
 }
 
+static int dumpStdQStringSet()
+{
+    std::set<QString> test;
+    test.insert(QLatin1String("item1"));
+    test.insert(QLatin1String("item2"));
+    prepareInBuffer("std::set", "local.stringset", "local.stringset", "QString");
+    qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(std::list<int>::allocator_type), 0, 0);
+    fputs(qDumpOutBuffer, stdout);
+    fputc('\n', stdout);
+    return 0;
+}
+
 static int dumpStdMapIntString()
 {
     std::map<int,std::string> test;
@@ -322,6 +334,22 @@ static int dumpStdMapIntString()
     return 0;
 }
 
+static int dumpStdMapStringString()
+{
+    typedef std::map<std::string,std::string> TestType;
+    TestType test;
+    const TestType::value_type entry("K", "V");
+    test.insert(entry);
+    const int valueOffset = (char*)&(entry.second) - (char*)&entry;
+    prepareInBuffer("std::map", "local.stdmapstringstring", "local.stdmapstringstring",
+                    "std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::less<int>@std::allocator<std::pair<const std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >");
+    qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::string), valueOffset, 0);
+    fputs(qDumpOutBuffer, stdout);
+    fputc('\n', stdout);
+    return 0;
+}
+
+
 static int dumpQObject()
 {
     // Requires the childOffset to be know, but that is not critical
@@ -398,7 +426,9 @@ static TypeDumpFunctionMap registerTypes()
     rc.insert("vector<wstring>", dumpStdWStringVector);
     rc.insert("set<int>", dumpStdIntSet);
     rc.insert("set<string>", dumpStdStringSet);
+    rc.insert("set<QString>", dumpStdQStringSet);
     rc.insert("map<int,string>", dumpStdMapIntString);
+    rc.insert("map<string,string>", dumpStdMapStringString);
     rc.insert("QObject", dumpQObject);
     rc.insert("QObjectList", dumpQObjectList);
     rc.insert("QVariant", dumpQVariant);
diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
index b4cd0bff6c782506b423aa37266c6638da2ff6a5..a42f88900d4208135bc4e60c4a7da81da2634c0f 100644
--- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp
+++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
@@ -100,7 +100,7 @@ static bool allocDebuggeeMemory(CdbComInterfaces *cif,
     OutputRedirector redir(cif->debugClient, &stringHandler);
     if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, allocCmd, errorMessage))
         return false;
-   // "Allocated 1000 bytes starting at 003a0000" .. hopefully never localized    
+   // "Allocated 1000 bytes starting at 003a0000" .. hopefully never localized
     bool ok = false;
     const QString output = stringHandler.result();
     const int lastBlank = output.lastIndexOf(QLatin1Char(' '));
@@ -176,7 +176,7 @@ static bool debuggeeLoadLibrary(IDebuggerManagerAccessForEngines *access,
         return false;
     // This will hit a breakpoint.
     if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, QString(QLatin1Char('g')), errorMessage))
-        return false;    
+        return false;
     const HRESULT hr = cif->debugControl->WaitForEvent(0, waitTimeOutMS);
     if (FAILED(hr)) {
         *errorMessage = msgComFailed("WaitForEvent", hr);
@@ -280,7 +280,7 @@ void CdbDumperHelper::moduleLoadHook(const QString &module, HANDLE debuggeeHandl
         if (m_tryInjectLoad && module.contains(QLatin1String("Qt"), Qt::CaseInsensitive)) {
             // Also shows up in the log window.
             m_manager->showStatusMessage(msgLoading(m_library, true), 10000);
-            QString errorMessage;            
+            QString errorMessage;
             SharedLibraryInjector sh(GetProcessId(debuggeeHandle));
             if (sh.remoteInject(m_library, false, &errorMessage)) {
                 m_state = InjectLoading;
@@ -408,7 +408,7 @@ static inline bool getSymbolAddress(CIDebugSymbols *sg,
 }
 
 bool CdbDumperHelper::initResolveSymbols(QString *errorMessage)
-{    
+{
     // Resolve the symbols we need (potentially namespaced).
     // There is a 'qDumpInBuffer' in QtCore as well.
     m_dumpObjectSymbol = QLatin1String("*qDumpObjectData440");
@@ -437,6 +437,7 @@ bool CdbDumperHelper::initResolveSymbols(QString *errorMessage)
 // Call query protocol to retrieve known types and sizes
 bool CdbDumperHelper::initKnownTypes(QString *errorMessage)
 {
+    const double dumperVersionRequired = 1.3;
     QByteArray output;
     QString callCmd;
     QTextStream(&callCmd) << ".call " << m_dumpObjectSymbol << "(1,0,0,0,0,0,0,0)";
@@ -447,6 +448,10 @@ bool CdbDumperHelper::initKnownTypes(QString *errorMessage)
     if (!m_helper.parseQuery(outData, QtDumperHelper::CdbDebugger)) {
      *errorMessage = QString::fromLatin1("Unable to parse the dumper output: '%1'").arg(QString::fromAscii(output));
     }
+    if (m_helper.dumperVersion() < dumperVersionRequired) {
+        *errorMessage = QtDumperHelper::msgDumperOutdated(dumperVersionRequired, m_helper.dumperVersion());
+        return false;
+    }
     if (loadDebug)
         qDebug() << Q_FUNC_INFO << m_helper.toString(true);
     return true;
@@ -521,7 +526,7 @@ bool CdbDumperHelper::callDumper(const QString &callCmd, const QByteArray &inBuf
         return false;
     }
     // see QDumper implementation
-    const char result = m_buffer[0];    
+    const char result = m_buffer[0];
     switch (result) {
     case 't':
         break;
@@ -574,7 +579,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
     }
 
     // Known type?
-    const QtDumperHelper::TypeData td = m_helper.typeData(wd.type);    
+    const QtDumperHelper::TypeData td = m_helper.typeData(wd.type);
     if (loadDebug)
         qDebug() << "dumpType" << wd.type << td;
     if (td.type == QtDumperHelper::UnknownType) {
@@ -596,7 +601,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
     // yet initialized in a particular breakpoint. That should be ignored.
     // Also fail for complex expression that were not cached/replaced by the helper.
     if (der == DumpExecuteSizeFailed || der == DumpComplexExpressionEncountered)
-        m_failedTypes.push_back(wd.type);    
+        m_failedTypes.push_back(wd.type);
     // log error
     *errorMessage = msgDumpFailed(wd, errorMessage);
     m_access->showDebuggerOutput(LogWarning, *errorMessage);
@@ -609,7 +614,7 @@ CdbDumperHelper::DumpExecuteResult
                                 QList<WatchData> *result, QString *errorMessage)
 {
     QByteArray inBuffer;
-    QStringList extraParameters;    
+    QStringList extraParameters;
     // Build parameter list.
     m_helper.evaluationParameters(wd, td, QtDumperHelper::CdbDebugger, &inBuffer, &extraParameters);
     // If the parameter list contains sizeof-expressions, execute them separately
diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
index 098b30c86c580c6ce7baf7a6ee7066ec45bedd98..5d82835f53dad00e411b14623ca7fd350413df5d 100644
--- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
+++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
@@ -86,10 +86,12 @@ static inline QString getSymbolString(IDebugSymbolGroup2 *sg,
                                       WideStringRetrievalFunction wsf,
                                       unsigned long index)
 {
-    static WCHAR nameBuffer[MAX_PATH + 1];
+    // Template type names can get quite long....
+    enum { BufSize = 1024 };
+    static WCHAR nameBuffer[BufSize + 1];
     // Name
     ULONG nameLength;
-    const HRESULT hr = (sg->*wsf)(index, nameBuffer, MAX_PATH, &nameLength);
+    const HRESULT hr = (sg->*wsf)(index, nameBuffer, BufSize, &nameLength);
     if (SUCCEEDED(hr)) {
         nameBuffer[nameLength] = 0;
         return QString::fromUtf16(reinterpret_cast<const ushort *>(nameBuffer));
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 597b12ebd1935455e1d95f343a3e2a5835e7a454..a714e85936767a63841d0ca8f4919b3bc3aa7b35 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -246,7 +246,7 @@ void GdbEngine::initializeVariables()
     m_address.clear();
     m_currentFunctionArgs.clear();
     m_currentFrame.clear();
-    m_dumperHelper = QtDumperHelper();
+    m_dumperHelper.clear();
 
     // FIXME: unhandled:
     //m_outputCodecState = QTextCodec::ConverterState();
@@ -3144,8 +3144,33 @@ void GdbEngine::rebuildModel()
     showToolTip();
 }
 
+static inline double getDumperVersion(const GdbMi &contents)
+{
+    const GdbMi dumperVersionG = contents.findChild("dumperversion");
+    if (dumperVersionG.type() != GdbMi::Invalid) {
+        bool ok;
+        const double v = QString::fromAscii(dumperVersionG.data()).toDouble(&ok);
+        if (ok)
+            return v;
+    }
+    return 1.0;
+}
+
+static void parseSizeCache(const GdbMi &contents, QtDumperHelper *dumperHelper)
+{
+    const GdbMi sizesList = contents.findChild("sizes");
+    if (sizesList.type() == GdbMi::Invalid)
+        return;
+    foreach(const GdbMi &c, sizesList.children()) {
+        const QString name = QString::fromAscii(c.name());
+        if (const int size = QString::fromAscii(c.data()).toInt())
+            dumperHelper->addSize(name, size);
+    }
+}
+
 void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const QVariant &)
 {
+    const double dumperVersionRequired = 1.0;
     m_dumperHelper.clear();
     //qDebug() << "DATA DUMPER TRIAL:" << record.toString();
 
@@ -3163,7 +3188,6 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
         //qDebug() << "FOUND QT VERSION:" << qtversion.toString() << m_qtVersion;
     }
     m_dumperHelper.setQtVersion(qtv);
-
     //qDebug() << "CONTENTS:" << contents.toString();
     //qDebug() << "SIMPLE DUMPERS:" << simple.toString();
 
@@ -3176,17 +3200,19 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
         if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
             m_debuggingHelperState = DebuggingHelperUnavailable;
         q->showStatusMessage(tr("Debugging helpers not found."));
-        //QMessageBox::warning(q->mainWindow(),
-        //    tr("Cannot find special data dumpers"),
-        //    tr("The debugged binary does not contain information needed for "
-        //            "nice display of Qt data types.\n\n"
-        //            "You might want to try including the file\n\n"
-        //            ".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n"
-        //            "into your project directly.")
-        //        );
     } else {
+        // Get version and sizes from dumpers. Expression cache
+        // currently causes errors.
+        const double dumperVersion = getDumperVersion(contents);
+        if (dumperVersion < dumperVersionRequired) {
+            qq->showQtDumperLibraryWarning(QtDumperHelper::msgDumperOutdated(dumperVersionRequired, dumperVersion));
+            m_debuggingHelperState = DebuggingHelperUnavailable;
+            return;
+        }
+        parseSizeCache(contents, &m_dumperHelper);
         m_debuggingHelperState = DebuggingHelperAvailable;
-        q->showStatusMessage(tr("%n custom dumpers found.", 0, m_dumperHelper.typeCount()));
+        const QString successMsg = tr("Dumper version %1, %n custom dumpers found.", 0, m_dumperHelper.typeCount()).arg(dumperVersion);
+        q->showStatusMessage(successMsg);
     }
     //qDebug() << m_dumperHelper.toString(true);
     //qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE";
diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp
index 555b6ac6cd4aabae1633b7f49fb21f68b0c0c10e..b82d54e75e1620a5743e3c2684d27ab5aaf24629 100644
--- a/src/plugins/debugger/watchutils.cpp
+++ b/src/plugins/debugger/watchutils.cpp
@@ -638,20 +638,30 @@ void QtDumperHelper::TypeData::clear()
 
 // ----------------- QtDumperHelper
 QtDumperHelper::QtDumperHelper() :
-    m_qtVersion(0)
+    m_qtVersion(0),
+    m_dumperVersion(1.0)
 {
     qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
+    setQClassPrefixes(QString());
 }
 
 void QtDumperHelper::clear()
 {
     m_nameTypeMap.clear();
     m_qtVersion = 0;
+    m_dumperVersion = 1.0;
     m_qtNamespace.clear();
     m_sizeCache.clear();
     qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
     m_expressionCache.clear();
-    m_dumperVersion.clear();
+    setQClassPrefixes(QString());
+}
+
+QString QtDumperHelper::msgDumperOutdated(double requiredVersion, double currentVersion)
+{
+    return QCoreApplication::translate("QtDumperHelper",
+                                       "Found a too-old version of the debugging helper library (%1); version %2 is required.").
+                                       arg(currentVersion).arg(requiredVersion);
 }
 
 static inline void formatQtVersion(int v, QTextStream &str)
@@ -685,7 +695,7 @@ QString QtDumperHelper::toString(bool debug) const
     return QCoreApplication::translate("QtDumperHelper",
                                        "%n known types, Qt version: %1, Qt namespace: %2 Dumper version: %3",
                                        0, QCoreApplication::CodecForTr,
-                                       m_nameTypeMap.size()).arg(qtVersionString(), nameSpace, m_dumperVersion);
+                                       m_nameTypeMap.size()).arg(qtVersionString(), nameSpace).arg(m_dumperVersion);
 }
 
 QtDumperHelper::Type QtDumperHelper::simpleType(const QString &simpleType) const
@@ -774,11 +784,11 @@ QtDumperHelper::ExpressionRequirement QtDumperHelper::expressionRequirements(Typ
     switch (t) {
     case QAbstractItemType:
     case QVectorType:
-    case StdMapType:
         return NeedsComplexExpression;
     case QMapType:
     case QMultiMapType:
     case QMapNodeType:
+    case StdMapType:
         return NeedsCachedExpression;
     default:
         // QObjectSlotType, QObjectSignalType need the signal number, which is numeric
@@ -1130,6 +1140,25 @@ bool QueryDumperParser::handleValue(const char *k, int size)
     return true;
 }
 
+static inline QString qClassName(const QString &qtNamespace, const char *className)
+{
+    if (qtNamespace.isEmpty())
+        return QString::fromAscii(className);
+    QString rc = qtNamespace;
+    rc += QLatin1String("::");
+    rc += QString::fromAscii(className);
+    return rc;
+}
+
+void QtDumperHelper::setQClassPrefixes(const QString &qNamespace)
+{
+    // Prefixes with namespaces
+    m_qPointerPrefix = qClassName(qNamespace, "QPointer");
+    m_qSharedPointerPrefix = qClassName(qNamespace, "QSharedPointer");
+    m_qSharedDataPointerPrefix = qClassName(qNamespace, "QSharedDataPointer");
+    m_qWeakPointerPrefix = qClassName(qNamespace, "QWeakPointer");
+}
+
 // parse a query
 bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
 {
@@ -1139,14 +1168,27 @@ bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
     clear();
     m_qtNamespace = parser.data().qtNameSpace;
     setQtVersion(parser.data().qtVersion);
+    setQClassPrefixes(m_qtNamespace);
     parseQueryTypes(parser.data().types, debugger);
     foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes)
         addSize(se.first, se.second);
     m_expressionCache = parser.data().expressionCache;
-    m_dumperVersion = parser.data().dumperVersion;
+    // Version
+    if (!parser.data().dumperVersion.isEmpty()) {
+        double dumperVersion;
+        bool ok;
+        dumperVersion = parser.data().dumperVersion.toDouble(&ok);
+        if (ok)
+            m_dumperVersion = dumperVersion;
+    }
     return true;
 }
 
+void QtDumperHelper::addExpression(const QString &expression, const QString &value)
+{
+    m_expressionCache.insert(expression, value);
+}
+
 void QtDumperHelper::addSize(const QString &name, int size)
 {
     // Special interest cases
@@ -1219,27 +1261,23 @@ QString QtDumperHelper::evaluationSizeofTypeExpression(const QString &typeName,
     return sizeofTypeExpression(typeName);
 }
 
-QtDumperHelper::SpecialSizeType QtDumperHelper::specialSizeType(const QString &typeName)
+QtDumperHelper::SpecialSizeType QtDumperHelper::specialSizeType(const QString &typeName) const
 {
     if (isPointerType(typeName))
         return PointerSize;
     static const QString intType = QLatin1String("int");
     static const QString stdAllocatorPrefix = QLatin1String("std::allocator");
-    static const QString qPointerPrefix = QLatin1String("QPointer");
-    static const QString qSharedPointerPrefix = QLatin1String("QSharedPointer");
-    static const QString qSharedDataPointerPrefix = QLatin1String("QSharedDataPointer");
-    static const QString qWeakPointerPrefix = QLatin1String("QWeakPointer");
     if (typeName == intType)
         return IntSize;
     if (typeName.startsWith(stdAllocatorPrefix))
         return StdAllocatorSize;
-    if (typeName.startsWith(qPointerPrefix))
+    if (typeName.startsWith(m_qPointerPrefix))
         return QPointerSize;
-    if (typeName.startsWith(qSharedPointerPrefix))
+    if (typeName.startsWith(m_qSharedPointerPrefix))
         return QSharedPointerSize;
-    if (typeName.startsWith(qSharedDataPointerPrefix))
+    if (typeName.startsWith(m_qSharedDataPointerPrefix))
         return QSharedDataPointerSize;
-    if (typeName.startsWith(qWeakPointerPrefix))
+    if (typeName.startsWith(m_qWeakPointerPrefix))
         return QWeakPointerSize;
     return SpecialSizeCount;
 }
@@ -1374,7 +1412,10 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
             int bracketPos = pairType.indexOf(QLatin1Char('<'));
             if (bracketPos != -1)
                 pairType.remove(0, bracketPos + 1);
-            bracketPos = pairType.indexOf(QLatin1Char('>'));
+            const QChar closingBracket = QLatin1Char('>');
+            bracketPos = pairType.lastIndexOf(closingBracket);
+            if (bracketPos != -1)
+                bracketPos = pairType.lastIndexOf(closingBracket, bracketPos - pairType.size() - 1);
             if (bracketPos != -1)
                 pairType.truncate(bracketPos + 1);
             extraArgs[2] = QLatin1String("(size_t)&(('");
diff --git a/src/plugins/debugger/watchutils.h b/src/plugins/debugger/watchutils.h
index d1d9b05215f9d407a5f68d9e4c01e3200d7777ae..9d02ad75f89015f04e9a82d2764fce3a14d4b928 100644
--- a/src/plugins/debugger/watchutils.h
+++ b/src/plugins/debugger/watchutils.h
@@ -91,7 +91,7 @@ struct QtDumperResult
         Child();
 
         int keyEncoded;
-        int valueEncoded;        
+        int valueEncoded;
         int childCount;
         bool valuedisabled;
         QString name;
@@ -174,6 +174,9 @@ public:
     QtDumperHelper();
     void clear();
 
+    double dumperVersion() const { return m_dumperVersion; }
+    void setDumperVersion(double v)  { m_dumperVersion = v; }
+
     int typeCount() const;
     // Look up a simple, non-template  type
     Type simpleType(const QString &simpleType) const;
@@ -219,9 +222,13 @@ public:
 
     QString toString(bool debug = false) const;
 
+    // Helpers for debuggers that use a different dumper parser.
     void addSize(const QString &name, int size);
+    void addExpression(const QString &expression, const QString &value);
+
+    static QString msgDumperOutdated(double requiredVersion, double currentVersion);
 
-private:        
+private:
     typedef QMap<QString, Type> NameTypeMap;
     typedef QMap<QString, int> SizeCache;
 
@@ -240,14 +247,21 @@ private:
                            QWeakPointerSize, QPointerSize, SpecialSizeCount };
 
     // Resolve name to enumeration or SpecialSizeCount (invalid)
-    static SpecialSizeType specialSizeType(const QString &t);
+    SpecialSizeType specialSizeType(const QString &t) const;
 
     int m_specialSizes[SpecialSizeCount];
 
     QMap<QString, QString> m_expressionCache;
     int m_qtVersion;
-    QString m_dumperVersion;
+    double m_dumperVersion;
     QString m_qtNamespace;
+
+    void setQClassPrefixes(const QString &qNamespace);
+
+    QString m_qPointerPrefix;
+    QString m_qSharedPointerPrefix;
+    QString m_qSharedDataPointerPrefix;
+    QString m_qWeakPointerPrefix;
 };
 
 QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d);