diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 759d86dd5c6..9937a79184a 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -2518,7 +2518,7 @@ class DumperBase: return if typeobj.isEnumType(): - #warn("ENUM VALUE: %s" % value) + #warn("ENUM VALUE: %s" % value.stringify()) self.putType(typeobj.name) self.putValue(value.display()) self.putNumChild(0) @@ -2651,24 +2651,22 @@ class DumperBase: error("INCONSISTENT TYPE: %s" % type(self.type)) def __str__(self): + #error("Not implemented") + return self.stringify() + + def stringify(self): self.check() addr = "None" if self.laddress is None else ("0x%x" % self.laddress) - #return self.display() return "Value(name='%s',type=%s,data=%s,address=%s,nativeValue=%s)" \ % (self.name, self.type, self.dumper.hexencode(self.ldata), addr, self.nativeValue) def display(self): + if self.type.lEnumType: + return self.type.enumDisplay(self.extractInteger(self.type.size() * 8, False)) simple = self.value() if simple is not None: return str(simple) - if self.type.lEnumType: - if self.nativeValue is not None: - if self.dumper.isLldb: - return "%s (%d)" % (self.nativeValue.GetValue(), self.nativeValue.GetValueAsSigned()) - else: - return "%s (%d)" % (self.nativeValue, self.nativeValue) - return self.integer() if self.type.lComplexType: if self.nativeValue is not None: if self.dumper.isLldb: @@ -2854,6 +2852,19 @@ class DumperBase: return val error("BAD DATA TO DEREFERENCE: %s %s" % (self.type, type(self))) + def extend(self, size): + if self.type.size() < size: + val = self.dumper.Value(self.dumper) + val.laddress = None + if sys.version_info[0] == 3: + val.ldata = self.ldata + bytes('\0' * (size - self.type.size()), encoding='latin1') + else: + val.ldata = self.ldata + bytes('\0' * (size - self.type.size())) + return val + if self.type.size() == size: + return self + error("NOT IMPLEMENTED") + def cast(self, typish): self.check() typeobj = self.dumper.createType(typish) @@ -2886,7 +2897,14 @@ class DumperBase: self.check() if self.ldata is not None: if len(self.ldata) > 0: - return self.ldata + if size is None: + return self.ldata + if size == len(self.ldata): + return self.ldata + if size < len(self.ldata): + return self.ldata[:size] + error("DATA PRESENT, BUT NOT BIG ENOUGH: %s WANT: %s" + % (self.stringify(), size)) if self.laddress is not None: if size is None: size = self.type.size() @@ -2918,7 +2936,12 @@ class DumperBase: if code is None: return None rawBytes = self.data(size) - return struct.unpack_from(code, rawBytes, 0)[0] + try: + return struct.unpack_from(code, rawBytes, 0)[0] + except: + pass + error("Cannot extract: Code: %s Bytes: %s Bitsize: %s Size: %s" + % (code, self.dumper.hexencode(rawBytes), bitsize, size)) def extractSomething(self, code, bitsize): self.check() @@ -2984,6 +3007,11 @@ class DumperBase: def __str__(self): self.check() return self.name + #error("Not implemented") + + def stringify(self): + return "Type(name='%s',bsize=%s,bpos=%s,enum=%s,native=%s)" \ + % (self.name, self.lbitsize, self.lbitpos, self.lEnumType, self.nativeType is not None) def __getitem__(self, index): if self.dumper.isInt(index): @@ -3202,6 +3230,11 @@ class DumperBase: return True return strippedName == "QStringList" and self.dumper.qtVersion() >= 0x050000 + def enumDisplay(self, intval): + if self.nativeType is not None: + return self.dumper.nativeTypeEnumDisplay(self.nativeType, intval) + return "%d" % intval + class Field: def __init__(self, dumper): self.dumper = dumper @@ -3271,6 +3304,11 @@ class DumperBase: typish.check() return typish if isinstance(typish, str): + if typish.startswith("enum "): + typish = typish[5:] + isEnum = True + else: + isEnum = False if typish[0] == 'Q': if typish in ("QByteArray", "QString", "QList", "QStringList"): typish = self.qtNamespace() + typish @@ -3287,14 +3325,12 @@ class DumperBase: elif typish == "QChar": typish = self.qtNamespace() + typish size = 2 - #res.lEnumType = False elif typish in ("quint32", "qint32"): typish = self.qtNamespace() + typish size = 4 #typeobj = self.Type(self) #typeobj.name = typish - #warn("CREATE TYPE: %s" % typish) nativeType = self.lookupNativeType(typish) # FIXME: Remove? #warn("FOUND NAT TYPE: %s" % dir(nativeType)) if nativeType is not None: @@ -3306,6 +3342,8 @@ class DumperBase: typeobj.name = typish if size is not None: typeobj.lbitsize = 8 * size + #warn("CREATE TYPE: %s" % typeobj) + typeobj.lEnumType = isEnum typeobj.check() return typeobj error("NEED TYPE, NOT %s" % type(typish)) diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index f5e6c1882e2..1bc91ee1f8f 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -379,6 +379,13 @@ class Dumper(DumperBase): if len(nativeFields) and nativeFields[0].is_base_class: return self.fromNativeType(nativeFields[0].type) + def nativeTypeEnumDisplay(self, nativeType, intval): + try: + val = gdb.parse_and_eval("(%s)%d" % (nativeType.name, intval)) + return "%s (%d)" % (val, intval) + except: + return "%d" % intval + def nativeTypeFields(self, nativeType): #warn("TYPE: %s" % nativeType) fields = [] diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index eebb6602b69..760009c216b 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -351,6 +351,18 @@ class Dumper(DumperBase): #warn(" GOT BASE FROM: %s" % t) return self.fromNativeType(nativeType.GetDirectBaseClassAtIndex(0).GetType()) + def nativeTypeEnumDisplay(self, nativeType, intval): + if hasattr(nativeType, 'get_enum_members_array'): + for enumMember in nativeType.get_enum_members_array(): + # Even when asking for signed we get unsigned with LLDB 3.8. + diff = enumMember.GetValueAsSigned() - intval + mask = (1 << nativeType.GetByteSize() * 8) - 1 + if diff & mask == 0: + path = nativeType.GetName().split('::') + path[-1] = enumMember.GetName() + return "%s (%d)" % ('::'.join(path), intval) + return "%d" % intval + def stateName(self, s): try: # See db.StateType diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index f4c9df6072a..5b0d22a4abd 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -620,12 +620,9 @@ def qdump__QFiniteStack(d, value): def qdump__QFlags(d, value): - i = value["i"] - try: - enumType = value.type.unqualified()[0] - d.putValue("%s (%s)" % (i.cast(enumType), i)) - except: - d.putValue("%s" % i) + i = value.split('{int}')[0] + enumType = value.type[0] + d.putValue(i.cast('enum ' + enumType.name).display()) d.putNumChild(0) @@ -923,25 +920,36 @@ def qdump__QLocale(d, value): # index = int(value["d"]["d"]["m_data"]...) #d.check(index >= 0) #d.check(index <= qqLocalesCount) + dd = value.extractPointer() + ns = d.qtNamespace() + prefix = "enum " + ns + "QLocale::" + (data, ref, numberOptions) = d.split("pi{int}", dd) + (languageId, scriptId, countryId, + decimal, group, listt, percent, zero, + minus, plus, exponential) \ + = d.split('{short}{short}{QChar}' + + '{QChar}{QChar}{short}{QChar}{QChar}' + + '{QChar}{QChar}{QChar}', data) d.putStringValue(d.call("const char *", value, "name")) d.putNumChild(1) if d.isExpanded(): - ns = d.qtNamespace() - with Children(d, childType=d.lookupType(ns + "QChar"), childNumChild=0): - d.putCallItem("country", value, "country") - d.putCallItem("language", value, "language") - d.putCallItem("measurementSystem", value, "measurementSystem") - d.putCallItem("numberOptions", value, "numberOptions") - d.putCallItem("timeFormat_(short)", value, - "timeFormat", ns + "QLocale::ShortFormat") - d.putCallItem("timeFormat_(long)", value, - "timeFormat", ns + "QLocale::LongFormat") - d.putCallItem("decimalPoint", value, "decimalPoint") - d.putCallItem("exponential", value, "exponential") - d.putCallItem("percent", value, "percent") - d.putCallItem("zeroDigit", value, "zeroDigit") - d.putCallItem("groupSeparator", value, "groupSeparator") - d.putCallItem("negativeSign", value, "negativeSign") + with Children(d): + d.putSubItem("country", countryId.extend(4).cast(prefix + "Country")) + d.putSubItem("language", languageId.extend(4).cast(prefix + "Language")) + d.putSubItem("numberOptions", numberOptions.cast(prefix + "NumberOptions")) + d.putSubItem("decimalPoint", decimal) + d.putSubItem("exponential", exponential) + d.putSubItem("percent", percent) + d.putSubItem("zeroDigit", zero) + d.putSubItem("groupSeparator", group) + d.putSubItem("negativeSign", minus) + d.putSubItem("positiveSign", plus) + d.putCallItem("measurementSystem", ns + "QLocale::MeasurementSystem", + value, "measurementSystem") + d.putCallItem("timeFormat_(short)", ns + "QString", + value, "timeFormat", ns + "QLocale::ShortFormat") + d.putCallItem("timeFormat_(long)", ns + "QString", + value, "timeFormat", ns + "QLocale::LongFormat") d.putFields(value) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 85c7e51412f..90c64fe8919 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -2216,10 +2216,19 @@ void tst_Dumpers::dumper_data() "QLocale::MeasurementSystem m1 = loc1.measurementSystem();\n" "unused(&loc0, &loc, &m, &loc1, &m1);\n") + CoreProfile() -// + Check("loc0", "\"en_US\"", "@QLocale") FIXME + CheckType("loc", "@QLocale") + CheckType("m", "@QLocale::MeasurementSystem") + Check("loc1", "\"en_US\"", "@QLocale") + + Check("loc1.country", "@QLocale::UnitedStates (225)", "@QLocale::Country") + + Check("loc1.language", "@QLocale::English (31)", "@QLocale::Language") + + Check("loc1.numberOptions", "@QLocale::DefaultNumberOptions (0)", "@QLocale::NumberOptions") + + Check("loc1.decimalPoint", "46", "@QChar") // . + + Check("loc1.exponential", "101", "@QChar") // e + + Check("loc1.percent", "37", "@QChar") // % + + Check("loc1.zeroDigit", "48", "@QChar") // 0 + + Check("loc1.groupSeparator", "44", "@QChar") // , + + Check("loc1.negativeSign", "45", "@QChar") // - + + Check("loc1.positiveSign", "43", "@QChar") // + + Check("m1", ValuePattern(".*Imperial.*System (1)"), Pattern(".*MeasurementSystem")); @@ -4855,6 +4864,19 @@ void tst_Dumpers::dumper_data() + Check("s32s", "-2147483648", "@qint32"); + QTest::newRow("Enum") + << Data("\n" + "enum Foo { a = -1000, b, c = 1, d };\n", + "Foo fa = a; unused(&fa);\n" + "Foo fb = b; unused(&fb);\n" + "Foo fc = c; unused(&fc);\n" + "Foo fd = d; unused(&fd);\n") + + Check("fa", "a (-1000)", "Foo") + + Check("fb", "b (-999)", "Foo") + + Check("fc", "c (1)", "Foo") + + Check("fd", "d (2)", "Foo"); + + QTest::newRow("Array") << Data("double a1[3][3];\n" "for (int i = 0; i != 3; ++i)\n"