diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index d9854814aef..e00a4b2bbff 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -2508,6 +2508,58 @@ def qdump__std____1__unique_ptr(d, value): d.putSubItem("data", i.dereference()) +def qform__std__unordered_map(): + return mapForms() + +def qdump__std__unordered_map(d, value): + try: + size = value["_M_element_count"] + start = value["_M_before_begin"]["_M_nxt"] + except: + size = value["_M_h"]["_M_element_count"] + start = value["_M_h"]["_M_bbegin"]["_M_node"]["_M_nxt"] + d.putItemCount(size) + d.putNumChild(size) + if d.isExpanded(): + p = pointerValue(start) + keyType = d.templateArgument(value.type, 0) + valueType = d.templateArgument(value.type, 1) + allocatorType = d.templateArgument(value.type, 4) + pairType = d.templateArgument(allocatorType, 0) + ptrSize = d.ptrSize() + if d.isMapCompact(keyType, valueType): + with Children(d, size, childType=valueType): + for i in d.childRange(): + pair = d.createValue(p + ptrSize, pairType) + with SubItem(d, i): + d.putField("iname", d.currentIName) + d.putName("[%s] %s" % (i, pair["first"])) + d.putValue(pair["second"]) + p = d.dereference(p) + else: + with Children(d, size, childType=pairType): + for i in d.childRange(): + d.putSubItem(i, d.createValue(p + ptrSize, pairType)) + p = d.dereference(p) + +def qdump__std__unordered_set(d, value): + try: + size = value["_M_element_count"] + start = value["_M_before_begin"]["_M_nxt"] + except: + size = value["_M_h"]["_M_element_count"] + start = value["_M_h"]["_M_bbegin"]["_M_node"]["_M_nxt"] + d.putItemCount(size) + d.putNumChild(size) + if d.isExpanded(): + p = pointerValue(start) + valueType = d.templateArgument(value.type, 0) + with Children(d, size, childType=valueType): + ptrSize = d.ptrSize() + for i in d.childRange(): + d.putSubItem(i, d.createValue(p + ptrSize, valueType)) + p = d.dereference(p) + def qedit__std__vector(expr, value): values = value.split(',') diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp index 65191194e26..5920a8e605f 100644 --- a/src/libs/cplusplus/CppRewriter.cpp +++ b/src/libs/cplusplus/CppRewriter.cpp @@ -586,6 +586,14 @@ CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn) if (setRE.indexIn(type) != -1) type.replace(setRE.cap(0), QString::fromLatin1("set<%1>").arg(inner)); + // std::unordered_set + QRegExp unorderedSetRE(QString::fromLatin1("unordered_set<%1, ?std::hash<%2>, ?std::equal_to<%3>, ?%4\\s*>") + .arg(innerEsc, innerEsc, innerEsc, allocEsc)); + unorderedSetRE.setMinimal(true); + QTC_ASSERT(unorderedSetRE.isValid(), return typeIn); + if (unorderedSetRE.indexIn(type) != -1) + type.replace(unorderedSetRE.cap(0), QString::fromLatin1("unordered_set<%1>").arg(inner)); + // std::map if (inner.startsWith(QLatin1String("std::pair<"))) { // search for outermost ',', split key and value @@ -621,6 +629,35 @@ CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn) type.replace(mapRE2.cap(0), QString::fromLatin1("map").arg(key, value)); } } + + // std::unordered_map + if (inner.startsWith(QLatin1String("std::pair<"))) { + // search for outermost ',', split key and value + int pos; + int level = 0; + for (pos = 10; pos < inner.size(); ++pos) { + int c = inner.at(pos).unicode(); + if (c == '<') + ++level; + else if (c == '>') + --level; + else if (c == ',' && level == 0) + break; + } + const QString key = chopConst(inner.mid(10, pos - 10)); + const QString keyEsc = QRegExp::escape(key); + // Get value: MSVC: 'pair', gcc: 'pair' + if (inner.at(++pos) == QLatin1Char(' ')) + pos++; + const QString value = inner.mid(pos, inner.size() - pos - 1).trimmed(); + const QString valueEsc = QRegExp::escape(value); + QRegExp mapRE1(QString::fromLatin1("unordered_map<%1, ?%2, ?std::hash<%3 ?>, ?std::equal_to<%4 ?>, ?%5\\s*>") + .arg(keyEsc, valueEsc, keyEsc, keyEsc, allocEsc)); + mapRE1.setMinimal(true); + QTC_ASSERT(mapRE1.isValid(), return typeIn); + if (mapRE1.indexIn(type) != -1) + type.replace(mapRE1.cap(0), QString::fromLatin1("unordered_map<%1, %2>").arg(key, value)); + } } type.replace(QLatin1Char('@'), QLatin1Char('*')); type.replace(QLatin1String(" >"), QLatin1String(">")); diff --git a/tests/auto/cplusplus/simplifytypes/tst_simplifytypestest.cpp b/tests/auto/cplusplus/simplifytypes/tst_simplifytypestest.cpp index 5f8349b54fb..79f2f5ee84a 100644 --- a/tests/auto/cplusplus/simplifytypes/tst_simplifytypestest.cpp +++ b/tests/auto/cplusplus/simplifytypes/tst_simplifytypestest.cpp @@ -42,6 +42,8 @@ const char *description[] = "g++_stringset", "g++_stringvector", "g++_wstringvector", + "g++_unordered_set", + "g++_unordered_map", "libc++_stringvector", "msvc_stdstring", "msvc_stdwstring", @@ -64,6 +66,10 @@ const char *input[] = "std::set, std::allocator >, std::less, std::allocator > >, std::allocator, std::allocator > > >", "std::vector, std::allocator >, std::allocator, std::allocator > > >", "std::vector, std::allocator >, std::allocator, std::allocator > > >", + +"std::unordered_set, std::equal_to, std::allocator >", +"std::unordered_map, std::equal_to, std::allocator > >", + // libc++ "std::__1::vector, std::__1::allocator >, std::__1::allocator, std::__1::allocator > > >", // MSVC @@ -88,6 +94,8 @@ const char *output[] = "std::set", "std::vector", "std::vector", + "std::unordered_set", + "std::unordered_map", // libc++ "std::vector", // MSVC diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 6c78c9d8f4c..b70f9840387 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -2951,6 +2951,44 @@ void tst_Dumpers::dumper_data() % Check("is", "", "std::ifstream") % Check("ok", "true", "bool"); + QTest::newRow("StdUnorderedMap1") + << Data("#include \n", + "std::unordered_map map;\n" + "map[11] = 1;\n" + "map[22] = 2;\n") + % Check("map", "<2 items>", "std::unordered_map") + % Cxx11Profile() + % Check("map.0", "[0] 22", "2", "unsigned int") + % Check("map.1", "[1] 11", "1", "unsigned int"); + + QTest::newRow("StdUnorderedMap2") + << Data("#include \n" + "#include \n", + "std::unordered_map map;\n" + "map[\"11.0\"] = 11.0;\n" + "map[\"22.0\"] = 22.0;\n") + % Cxx11Profile() + % Check("map", "<2 items>", "std::unordered_map") + //% Check("map.0", "[0]", "", "std::pair") + % Check("map.0.first", "\"22.0\"", "std::string") + % Check("map.0.second", "22", "float") + //% Check("map.1", "[1]", "", "std::pair") + % Check("map.1.first", "\"11.0\"", "std::string") + % Check("map.1.second", "11", "float"); + + QTest::newRow("StdUnorderedSet1") + << Data("#include \n", + "std::unordered_set set;\n" + "set.insert(11);\n" + "set.insert(22);\n" + "set.insert(33);\n") + % Cxx11Profile() + % Check("set", "<3 items>", "std::unordered_set") + % Check("set.0", "[0]", "33", "int") + % Check("set.1", "[1]", "22", "int") + % Check("set.2", "[2]", "11", "int"); + + QTest::newRow("ItemModel") << Data("#include \n", "QStandardItemModel m;\n"