diff --git a/share/qtcreator/dumper/dumper.py b/share/qtcreator/dumper/dumper.py
index 61770db911a..32a1e5f6f5f 100644
--- a/share/qtcreator/dumper/dumper.py
+++ b/share/qtcreator/dumper/dumper.py
@@ -89,12 +89,39 @@ def hasInferiorThreadList():
except:
return False
+def dynamicTypeName(value):
+ #vtbl = str(parseAndEvaluate("{int(*)(int)}%s" % long(value.address)))
+ vtbl = gdb.execute("info symbol {int*}%s" % long(value.address),
+ to_string = True)
+ pos1 = vtbl.find("vtable ")
+ if pos1 != -1:
+ pos1 += 11
+ pos2 = vtbl.find(" +", pos1)
+ if pos2 != -1:
+ return vtbl[pos1 : pos2]
+ return str(value.type)
+
def upcast(value):
try:
- type = value.dynamic_type
- return value.cast(type)
+ return value.cast(value.dynamic_type)
except:
- return value
+ pass
+ #try:
+ # return value.cast(lookupType(dynamicTypeName(value)))
+ #except:
+ # pass
+ return value
+
+def expensiveUpcast(value):
+ try:
+ return value.cast(value.dynamic_type)
+ except:
+ pass
+ try:
+ return value.cast(lookupType(dynamicTypeName(value)))
+ except:
+ pass
+ return value
typeCache = {}
@@ -956,6 +983,7 @@ class Dumper:
elif arg.startswith("watchers:"):
watchers = base64.b16decode(arg[pos:], True)
+ self.useDynamicType = "dyntype" in options
self.useFancy = "fancy" in options
self.passExceptions = "pe" in options
self.autoDerefPointers = "autoderef" in options
@@ -1542,30 +1570,26 @@ class Dumper:
warn("WRONG ASSUMPTION HERE: %s " % type.code)
check(False)
- #vtbl = str(parseAndEvaluate("{int(*)(int)}%s" % long(value.address)))
- vtbl = gdb.execute("info symbol {int*}%s" % long(value.address),
- to_string = True)
- pos1 = vtbl.find("vtable ")
- if pos1 != -1:
- pos1 += 11
- pos2 = vtbl.find(" +", pos1)
- if pos2 != -1:
- self.putType(vtbl[pos1 : pos2], 1)
+
+ if self.useDynamicType:
+ dtypeName = dynamicTypeName(value)
+ else:
+ dtypeName = typeName
if self.useFancy and (format is None or format >= 1):
self.putAddress(value.address)
- self.putType(typeName)
+ self.putType(dtypeName)
- if typeName in qqDumpers:
- qqDumpers[typeName](self, value)
+ if dtypeName in qqDumpers:
+ qqDumpers[dtypeName](self, expensiveUpcast(value))
return
- nsStrippedType = self.stripNamespaceFromType(typeName)\
+ nsStrippedType = self.stripNamespaceFromType(dtypeName)\
.replace("::", "__")
#warn(" STRIPPED: %s" % nsStrippedType)
#warn(" DUMPERS: %s" % (nsStrippedType in qqDumpers))
if nsStrippedType in qqDumpers:
- qqDumpers[nsStrippedType](self, value)
+ qqDumpers[nsStrippedType](self, expensiveUpcast(value))
return
# Is this derived from QObject?
@@ -1580,7 +1604,7 @@ class Dumper:
fields = extractFields(type)
#fields = type.fields()
- self.putType(typeName)
+ self.putType(dtypeName)
self.putAddress(value.address)
self.putValue("{...}")
diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index 86fac6ecf08..b50a72b9c9d 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -357,6 +357,14 @@ DebuggerSettings::DebuggerSettings(QSettings *settings)
item->setValue(false);
insertItem(AutoEnrichParameters, item);
+ item = new SavedAction(this);
+ item->setSettingsKey(debugModeGroup, QLatin1String("UseDynamicType"));
+ item->setText(tr("Use dynamic object type for display"));
+ item->setCheckable(true);
+ item->setDefaultValue(true);
+ item->setValue(true);
+ insertItem(UseDynamicType, item);
+
item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("TargetAsync"));
item->setCheckable(true);
diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h
index 3f0c4bb86f8..fadfce9b245 100644
--- a/src/plugins/debugger/debuggeractions.h
+++ b/src/plugins/debugger/debuggeractions.h
@@ -120,6 +120,7 @@ enum DebuggerActionCode
GdbStartupCommands,
GdbWatchdogTimeout,
AutoEnrichParameters,
+ UseDynamicType,
TargetAsync,
// Stack
diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp
index 2828ee0ec63..01a60a9a294 100644
--- a/src/plugins/debugger/gdb/gdboptionspage.cpp
+++ b/src/plugins/debugger/gdb/gdboptionspage.cpp
@@ -88,6 +88,8 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent)
m_ui->checkBoxLoadGdbInit);
m_group.insert(debuggerCore()->action(AutoEnrichParameters),
m_ui->checkBoxAutoEnrichParameters);
+ m_group.insert(debuggerCore()->action(UseDynamicType),
+ m_ui->checkBoxUseDynamicType);
m_group.insert(debuggerCore()->action(TargetAsync),
m_ui->checkBoxTargetAsync);
m_group.insert(debuggerCore()->action(AdjustBreakpointLocations),
@@ -120,6 +122,7 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent)
<< sep << m_ui->groupBoxLocations->title()
<< sep << m_ui->checkBoxLoadGdbInit->text()
<< sep << m_ui->checkBoxTargetAsync->text()
+ << sep << m_ui->checkBoxUseDynamicType->text()
<< sep << m_ui->labelGdbWatchdogTimeout->text()
<< sep << m_ui->checkBoxEnableReverseDebugging->text()
<< sep << m_ui->checkBoxSkipKnownFrames->text()
diff --git a/src/plugins/debugger/gdb/gdboptionspage.ui b/src/plugins/debugger/gdb/gdboptionspage.ui
index a53133d4aac..a63038e07ab 100644
--- a/src/plugins/debugger/gdb/gdboptionspage.ui
+++ b/src/plugins/debugger/gdb/gdboptionspage.ui
@@ -92,6 +92,16 @@ on slow machines. In this case, the value should be increased.
-
+
+
+ This specifies whether the dynamic or the static type of objects will be displayed. Choosing the dynamic type might be slower.
+
+
+ Use dynamic object type for display
+
+
+
+ -
This allows or inhibits reading the user's default .gdbinit file on debugger startup.
@@ -101,14 +111,14 @@ on slow machines. In this case, the value should be increased.
- -
+
-
Use asynchronous mode to control the inferior
- -
+
-
This adds common paths to locations of debug information at debugger startup.
@@ -118,21 +128,21 @@ on slow machines. In this case, the value should be increased.
- -
+
-
Stop when a qWarning is issued
- -
+
-
Stop when a qFatal is issued
- -
+
-
<html><head/><body><p>Selecting this enables reverse debugging.</p><.p><b>Note:</b> This feature is very slow and unstable on the GDB side. It exhibits unpredictable behavior when going backwards over system calls and is very likely to destroy your debugging session.</p><body></html>
diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp
index 17f54be00d9..81baea0fe9c 100644
--- a/src/plugins/debugger/gdb/pythongdbengine.cpp
+++ b/src/plugins/debugger/gdb/pythongdbengine.cpp
@@ -93,12 +93,14 @@ void GdbEngine::updateLocalsPython(const UpdateParameters ¶ms)
const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty();
QByteArray options;
+ if (alwaysVerbose)
+ options += "pe,";
if (debuggerCore()->boolSetting(UseDebuggingHelpers))
options += "fancy,";
if (debuggerCore()->boolSetting(AutoDerefPointers))
options += "autoderef,";
- if (alwaysVerbose)
- options += "pe,";
+ if (debuggerCore()->boolSetting(UseDynamicType))
+ options += "dyntype,";
if (options.isEmpty())
options += "defaults,";
if (params.tryPartial)
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index 28bef18d5c4..7149becdbe3 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -864,6 +864,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
menu.addAction(debuggerCore()->action(ShowStdNamespace));
menu.addAction(debuggerCore()->action(ShowQtNamespace));
menu.addAction(debuggerCore()->action(SortStructMembers));
+ menu.addAction(debuggerCore()->action(UseDynamicType));
QAction *actClearCodeModelSnapshot
= new QAction(tr("Refresh Code Model Snapshot"), &menu);
diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp
index 17a528aae92..1e544180c93 100644
--- a/tests/manual/debugger/simple/simple_test_app.cpp
+++ b/tests/manual/debugger/simple/simple_test_app.cpp
@@ -4148,7 +4148,7 @@ namespace gdb13393 {
S s(d);
Base *ptr = &d;
const Base *ptrConst = &d;
- Base& ref = d;
+ Base &ref = d;
const Base &refConst = d;
Base **ptrToPtr = &ptr;
#if USE_BOOST