Debugger: Use integer from native GDB value for typedef

Extend the solution from

    commit d86cf5e235
    Author: Michael Weghorn <m.weghorn@posteo.de>
    Date:   Thu Sep 24 12:02:06 2020 +0200

        Debugger: Retrieve and remember int from native GDB value

to also retrieve the int representation for numeric values
from the corresponding native gdb.Value if a typedef to
an integer or bool type is used, not only when an integer
type is used directly.

This makes expressions for bifield members in the
debugger's expression view show the correct value
when the type of those bitfield members is a typedef
to an integer type.

Extend the "Bitfields" dumper test accordingly.

One real world example where incorrect values were
previously shown is GtkWidgetPrivate from the
GTK library [1].

[1] ebc84a6185/gtk/gtkwidgetprivate.h (L39-76)

Change-Id: Ib39e00ebbfc8d7d9ab10dc89af61f37ec41fb4ee
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Michael Weghorn
2024-05-07 15:35:34 +02:00
parent b36ddaf8ec
commit 23b7ac84a9
2 changed files with 15 additions and 3 deletions

View File

@@ -265,6 +265,12 @@ class Dumper(DumperBase):
except: except:
# GDB only support converting integers of max. 64 bits to Python int as of now # GDB only support converting integers of max. 64 bits to Python int as of now
pass pass
elif code == gdb.TYPE_CODE_TYPEDEF:
targetType = nativeType.strip_typedefs().unqualified()
if targetType.code in [gdb.TYPE_CODE_BOOL, gdb.TYPE_CODE_INT]:
typeid = val.typeid
val = self.fromNativeValue(nativeValue.cast(targetType))
val.typeid = typeid
#elif code == gdb.TYPE_CODE_ARRAY: #elif code == gdb.TYPE_CODE_ARRAY:
# val.type.ltarget = nativeValue[0].type.unqualified() # val.type.ltarget = nativeValue[0].type.unqualified()
return val return val

View File

@@ -6243,15 +6243,19 @@ void tst_Dumpers::dumper_data()
QTest::newRow("Bitfields") QTest::newRow("Bitfields")
<< Data("", << Data("",
"typedef int gint;\n"
"typedef unsigned int guint;\n"
"enum E { V1, V2 };\n" "enum E { V1, V2 };\n"
"struct S\n" "struct S\n"
"{\n" "{\n"
" S() : front(13), x(2), y(3), z(39), e(V2), c(1), b(0), f(5)," " S() : front(13), x(2), y(3), z(39), t1(1), t2(1), e(V2), c(1), b(0), f(5),"
" g(46), h(47), d(6), i(7) {}\n" " g(46), h(47), d(6), i(7) {}\n"
" unsigned int front;\n" " unsigned int front;\n"
" unsigned int x : 3;\n" " unsigned int x : 3;\n"
" unsigned int y : 4;\n" " unsigned int y : 4;\n"
" unsigned int z : 18;\n" " unsigned int z : 18;\n"
" gint t1 : 2;\n"
" guint t2 : 2;\n"
" E e : 3;\n" " E e : 3;\n"
" bool c : 1;\n" " bool c : 1;\n"
" bool b;\n" " bool b;\n"
@@ -6284,7 +6288,7 @@ void tst_Dumpers::dumper_data()
+ Check("s.e", "V2 (1)", TypePattern("main::[a-zA-Z0-9_]*::E")) % CdbEngine + Check("s.e", "V2 (1)", TypePattern("main::[a-zA-Z0-9_]*::E")) % CdbEngine
// checks for the "Expressions" view, GDB-only for now // checks for the "Expressions" view, GDB-only for now
+ Watcher("watch.1", "s;s.b;s.c;s.f;s.d;s.i;s.x;s.y;s.z;s.e;s.g;s.h;s.front") + Watcher("watch.1", "s;s.b;s.c;s.f;s.d;s.i;s.x;s.y;s.z;s.e;s.g;s.h;s.front;s.t1;s.t2")
+ Check("watch.1.0", "s", "", "S") % GdbEngine + Check("watch.1.0", "s", "", "S") % GdbEngine
+ Check("watch.1.1", "s.b", "0", "bool") % GdbEngine + Check("watch.1.1", "s.b", "0", "bool") % GdbEngine
+ Check("watch.1.2", "s.c", "1", "bool") % GdbEngine + Check("watch.1.2", "s.c", "1", "bool") % GdbEngine
@@ -6297,7 +6301,9 @@ void tst_Dumpers::dumper_data()
+ Check("watch.1.9", "s.e", "V2 (1)", "E") % GdbEngine + Check("watch.1.9", "s.e", "V2 (1)", "E") % GdbEngine
+ Check("watch.1.10", "s.g", "46", "char") % GdbEngine + Check("watch.1.10", "s.g", "46", "char") % GdbEngine
+ Check("watch.1.11", "s.h", "47", "char") % GdbEngine + Check("watch.1.11", "s.h", "47", "char") % GdbEngine
+ Check("watch.1.12", "s.front", "13", "unsigned int") % GdbEngine; + Check("watch.1.12", "s.front", "13", "unsigned int") % GdbEngine
+ Check("watch.1.13", "s.t1", "1", "gint") % GdbEngine
+ Check("watch.1.14", "s.t2", "1", "guint") % GdbEngine;
QTest::newRow("Bitfield2") QTest::newRow("Bitfield2")