diff --git a/src/libs/qtcreatorcdbext/containers.cpp b/src/libs/qtcreatorcdbext/containers.cpp
index a59bdf52c47e0a2fdaa75fce01b8732e63664189..9e28cf0aa4566ed628a25fa810762450870fbbbf 100644
--- a/src/libs/qtcreatorcdbext/containers.cpp
+++ b/src/libs/qtcreatorcdbext/containers.cpp
@@ -43,6 +43,8 @@ typedef AbstractSymbolGroupNode::AbstractSymbolGroupNodePtrVector AbstractSymbol
 typedef std::vector<SymbolGroupValue> SymbolGroupValueVector;
 typedef std::vector<int>::size_type VectorIndexType;
 
+enum { debugVector  = 0 };
+
 // Read a pointer array from debuggee memory (ULONG64/32 according pointer size)
 static void *readPointerArray(ULONG64 address, unsigned count, const SymbolGroupValueContext &ctx)
 {
@@ -76,6 +78,18 @@ static inline void dump64bitPointerArray(std::ostream &os, const void *a, int co
     dumpHexArray(os, reinterpret_cast<const ULONG64 *>(a), count);
 }
 
+// Fix the inner type of containers (that is, make it work smoothly with AddSymbol)
+// by prefixing it with the module except for well-known types like STL/Qt types
+static inline std::string fixInnerType(std::string type, const SymbolGroupValueContext &ctx)
+{
+    const std::string stripped = SymbolGroupValue::stripClassPrefixes(type);
+    const KnownType kt = knownType(stripped, false);
+    // Simple types and STL/Q-types (inexplicably) are fast.
+    if (kt & (KT_POD_Type|KT_Qt_Type|KT_STL_Type))
+        return stripped;
+    return SymbolGroupValue::resolveType(stripped, ctx);
+}
+
 // Return size from an STL vector (last/first iterators).
 static inline int msvcStdVectorSize(const SymbolGroupValue &v)
 {
@@ -89,7 +103,7 @@ static inline int msvcStdVectorSize(const SymbolGroupValue &v)
                 return 0;
             // Subtract the pointers: We need to do the pointer arithmetics ourselves
             // as we get char *pointers.
-            const std::string innerType = SymbolGroupValue::stripPointerType(myFirstPtrV.type());
+            const std::string innerType = fixInnerType(SymbolGroupValue::stripPointerType(myFirstPtrV.type()), v.context());
             const size_t size = SymbolGroupValue::sizeOf(innerType.c_str());
             if (size == 0)
                 return -1;
@@ -324,10 +338,15 @@ static inline AbstractSymbolGroupNodePtrVector
         SymbolGroupValue myFirst = vec[unsigned(0)]["_Myfirst"]; // MSVC2010
         if (!myFirst)
             myFirst = vec["_Myfirst"]; // MSVC2008
-        if (myFirst)
-            if (const ULONG64 address = myFirst.pointerValue())
-                return arrayChildList(n->symbolGroup(), address,
-                                      SymbolGroupValue::stripPointerType(myFirst.type()), count);
+        if (myFirst) {
+            if (const ULONG64 address = myFirst.pointerValue()) {
+                const std::string firstType = myFirst.type();
+                const std::string innerType = fixInnerType(SymbolGroupValue::stripPointerType(firstType), ctx);
+                if (debugVector)
+                    DebugPrint() << n->name() << " inner type: '" << innerType << "' from '" << firstType << '\'';
+                return arrayChildList(n->symbolGroup(), address, innerType, count);
+            }
+        }
     }
     return AbstractSymbolGroupNodePtrVector();
 }
@@ -620,9 +639,12 @@ static inline AbstractSymbolGroupNodePtrVector
         // QVector<T>: p/array is declared as array of T. Dereference first
         // element to obtain address.
         const SymbolGroupValue vec(n, ctx);
-        if (const SymbolGroupValue firstElementV = vec["p"]["array"][unsigned(0)])
-            if (const ULONG64 arrayAddress = firstElementV.address())
-                    return arrayChildList(n->symbolGroup(), arrayAddress, firstElementV.type(), count);
+        if (const SymbolGroupValue firstElementV = vec["p"]["array"][unsigned(0)]) {
+            if (const ULONG64 arrayAddress = firstElementV.address()) {
+                const std::string fixedInnerType = fixInnerType(firstElementV.type(), ctx);
+                return arrayChildList(n->symbolGroup(), arrayAddress, fixedInnerType, count);
+            }
+        }
     }
     return AbstractSymbolGroupNodePtrVector();
 }
@@ -663,7 +685,7 @@ static inline AbstractSymbolGroupNodePtrVector
      const std::vector<std::string> innerTypes = v.innerTypes();
      if (innerTypes.size() != 1)
          return AbstractSymbolGroupNodePtrVector();
-     const std::string &innerType = innerTypes.front();
+     const std::string innerType = fixInnerType(innerTypes.front(), v.context());
      const unsigned innerTypeSize = SymbolGroupValue::sizeOf(innerType.c_str());
      if (!innerTypeSize)
          return AbstractSymbolGroupNodePtrVector();
diff --git a/src/libs/qtcreatorcdbext/knowntype.h b/src/libs/qtcreatorcdbext/knowntype.h
index f88ad6074810b6f4c7891514dc3d308a84e6f9dc..ebabf902cacaa132574c49338f6fff6ab2a072ba 100644
--- a/src/libs/qtcreatorcdbext/knowntype.h
+++ b/src/libs/qtcreatorcdbext/knowntype.h
@@ -38,12 +38,19 @@
 enum KnownType
 {
     KT_Unknown =0,
-    KT_Qt_Type = 0x10000,
-    KT_Qt_PrimitiveType = 0x20000,
-    KT_Qt_MovableType = 0x40000,
-    KT_STL_Type = 0x80000,
-    KT_ContainerType = 0x100000,
-    KT_HasSimpleDumper = 0x200000,
+    KT_POD_Type = 0x10000,
+    KT_Qt_Type = 0x20000,
+    KT_Qt_PrimitiveType = 0x40000,
+    KT_Qt_MovableType = 0x80000,
+    KT_STL_Type = 0x100000,
+    KT_ContainerType = 0x200000,
+    KT_HasSimpleDumper = 0x400000,
+    // PODs
+    KT_Char = KT_POD_Type + 1,
+    KT_UnsignedChar = KT_POD_Type + 2,
+    KT_IntType = KT_POD_Type + 3,         // any signed short, long, int
+    KT_UnsignedIntType = KT_POD_Type + 4, // any unsigned int
+    KT_FloatType = KT_POD_Type + 5,       // float, double
     // Qt Basic
     KT_QChar = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 1,
     KT_QByteArray = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 2,
@@ -156,7 +163,7 @@ enum KnownType
     KT_StdDeque =  KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 4,
     KT_StdSet =  KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 5,
     KT_StdMap =  KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 6,
-    KT_StdMultiMap =  KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 7,
+    KT_StdMultiMap =  KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 7
 };
 
 #endif // KNOWNTYPE_H
diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
index 1ce1899cbc682f5116a3c95a8cac2c8840a3b65c..73e6f5c94e7eda28969dcafe20ec6b84cf98a451 100644
--- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
+++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
@@ -252,7 +252,7 @@ std::string SymbolGroupValue::error() const
 
 bool SymbolGroupValue::isPointerType(const std::string &t)
 {
-    return endsWith(t, " *");
+    return endsWith(t, '*');
 }
 
 unsigned SymbolGroupValue::pointerSize()
@@ -277,7 +277,25 @@ unsigned SymbolGroupValue::fieldOffset(const char *type, const char *field)
 
 std::string SymbolGroupValue::stripPointerType(const std::string &t)
 {
-    return isPointerType(t) ? t.substr(0, t.size() - 2) : t;
+    // 'Foo *' -> 'Foo', 'Bar **' -> 'Bar *'.
+    if (endsWith(t, "**"))
+        return t.substr(0, t.size() - 1);
+    if (endsWith(t, " *"))
+        return t.substr(0, t.size() - 2);
+    return t;
+}
+
+// Strip "class Foo", "struct Bar"-> "Foo", "Bar "
+std::string SymbolGroupValue::stripClassPrefixes(const std::string &type)
+{
+    std::string rc = type;
+    if (rc.compare(0, 6, "class ") == 0) {
+        rc.erase(0, 6);
+    } else {
+        if (rc.compare(0, 7, "struct ") == 0)
+            rc.erase(0, 7);
+    }
+    return rc;
 }
 
 std::string SymbolGroupValue::addPointerType(const std::string &t)
@@ -371,13 +389,7 @@ std::string QtInfo::prependModuleAndNameSpace(const std::string &type,
                                               const std::string &aNameSpace)
 {
     // Strip the prefixes "class ", "struct ".
-    std::string rc = type;
-    if (rc.compare(0, 6, "class ") == 0) {
-        rc.erase(0, 6);
-    } else {
-        if (rc.compare(0, 7, "struct ") == 0)
-            rc.erase(0, 7);
-    }
+    std::string rc = SymbolGroupValue::stripClassPrefixes(type);
     // Is the namespace 'nsp::' missing?
     if (!aNameSpace.empty()) {
         const bool nameSpaceMissing = rc.size() <= aNameSpace.size()
@@ -440,6 +452,42 @@ std::list<std::string>
     return rc;
 }
 
+// Resolve a type, that is, obtain its module name ('QString'->'QtCored4!QString')
+std::string SymbolGroupValue::resolveType(const std::string &type, const SymbolGroupValueContext &ctx)
+{
+    enum { BufSize = 512 };
+
+    if (type.empty() || type.find('!') != std::string::npos)
+        return type;
+
+    const std::string stripped = SymbolGroupValue::stripClassPrefixes(type);
+
+    // Obtain the base address of the module using an obscure ioctl() call.
+    // See inline implementation of GetTypeSize() and docs.
+    SYM_DUMP_PARAM symParameters = { sizeof (SYM_DUMP_PARAM), (PUCHAR)stripped.c_str(), DBG_DUMP_NO_PRINT, 0,
+                                     NULL, NULL, NULL, 0, NULL };
+    const ULONG typeSize = Ioctl(IG_GET_TYPE_SIZE, &symParameters, symParameters.size);
+    if (!typeSize || !symParameters.ModBase) // Failed?
+        return type;
+    ULONG index = 0;
+    ULONG64 base = 0;
+    // Convert module base address to module index
+    HRESULT hr = ctx.symbols->GetModuleByOffset(symParameters.ModBase, 0, &index, &base);
+    if (FAILED(hr))
+        return type;
+    // Obtain module name
+    char buf[BufSize];
+    buf[0] = '\0';
+    hr = ctx.symbols->GetModuleNameString(DEBUG_MODNAME_MODULE, index, base, buf, BufSize, 0);
+    if (FAILED(hr))
+        return type;
+
+    std::string rc = buf;
+    rc.push_back('!');
+    rc += type;
+    return rc;
+}
+
 // get the inner types: "QMap<int, double>" -> "int", "double"
 std::vector<std::string> SymbolGroupValue::innerTypesOf(const std::string &t)
 {
@@ -567,8 +615,45 @@ static inline void formatMilliSeconds(std::wostream &str, int milliSecs)
 static const char stdStringTypeC[] = "std::basic_string<char,std::char_traits<char>,std::allocator<char> >";
 static const char stdWStringTypeC[] = "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >";
 
+static KnownType knownPODTypeHelper(const std::string &type)
+{
+    if (type.empty())
+        return KT_Unknown;
+    switch (type.at(0)) {
+    case 'c':
+        if (type == "char")
+            return KT_Char;
+        break;
+    case 'd':
+        if (type == "double")
+            return KT_FloatType;
+        break;
+    case 'f':
+        if (type == "float")
+            return KT_FloatType;
+        break;
+    case 'l':
+        if (!type.compare(0, 4, "long"))
+            return KT_IntType;
+        break;
+    case 'i':
+        if (!type.compare(0, 3, "int"))
+            return KT_IntType;
+        break;
+    case 's':
+        if (!type.compare(0, 5, "short"))
+            return KT_IntType;
+        break;
+    case 'u':
+        if (!type.compare(0, 8, "unsigned"))
+            return type == "unsigned char" ? KT_UnsignedChar : KT_UnsignedIntType;
+        break;
+    }
+    return KT_Unknown;
+}
+
 // Determine type starting from a position (with/without 'class '/'struct ' prefix).
-static KnownType knownTypeHelper(const std::string &type, std::string::size_type pos)
+static KnownType knownClassTypeHelper(const std::string &type, std::string::size_type pos)
 {
     // Strip pointer types.
     const std::wstring::size_type compareLen =
@@ -901,20 +986,23 @@ KnownType knownType(const std::string &type, bool hasClassPrefix)
 {
     if (type.empty())
         return KT_Unknown;
+    const KnownType podType = knownPODTypeHelper(type);
+    if (podType != KT_Unknown)
+        return podType;
     if (hasClassPrefix) {
         switch (type.at(0)) { // Check 'class X' or 'struct X'
         case 'c':
             if (!type.compare(0, 6, "class "))
-                return knownTypeHelper(type, 6);
+                return knownClassTypeHelper(type, 6);
             break;
         case 's':
             if (!type.compare(0, 7, "struct "))
-                return knownTypeHelper(type, 7);
+                return knownClassTypeHelper(type, 7);
             break;
         }
     } else {
         // No prefix, full check
-        return knownTypeHelper(type, 0);
+        return knownClassTypeHelper(type, 0);
     }
     return KT_Unknown;
 }
diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.h b/src/libs/qtcreatorcdbext/symbolgroupvalue.h
index 4c3cd00ab808679e6d69a57fd3badc4cedcef883..9a0ea67536f5affab4886a87c541e7fa6ccdb80c 100644
--- a/src/libs/qtcreatorcdbext/symbolgroupvalue.h
+++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.h
@@ -101,9 +101,15 @@ public:
     // Offset of structure field: "!moduleQMapNode<K,T>", "value".
     static unsigned fieldOffset(const char *type, const char *field);
     static std::string stripPointerType(const std::string &);
+    // Strip "class ", "struct "
+    static std::string stripClassPrefixes(const std::string &);
     static std::string addPointerType(const std::string &);
     static std::string stripArrayType(const std::string &);
     static bool isPointerType(const std::string &);
+    // Resolve a type, that is, obtain its module name ('QString'->'QtCored4!QString')
+    // Some operations on types (like adding symbols may fail non-deterministically
+    // or be slow when the module specification is omitted).
+    static std::string resolveType(const std::string &type, const SymbolGroupValueContext &ctx);
     static std::list<std::string> resolveSymbol(const char *pattern,
                                                 const SymbolGroupValueContext &c,
                                                 std::string *errorMessage = 0);