From c6e88eec0e990841ac1dfe40e78e83d58ecd4827 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Mon, 15 Feb 2010 16:02:41 +0100
Subject: [PATCH] debugger: implement basic support for gdb's 'return' command

Returning a value is not yet supported.
---
 src/plugins/debugger/debuggeractions.h   |  1 +
 src/plugins/debugger/debuggerconstants.h | 10 +++++++---
 src/plugins/debugger/debuggermanager.cpp | 21 ++++++++++++++++++---
 src/plugins/debugger/debuggermanager.h   |  1 +
 src/plugins/debugger/debuggerplugin.cpp  |  5 +++++
 src/plugins/debugger/gdb/gdbengine.cpp   | 18 +++++++++++++++++-
 src/plugins/debugger/gdb/gdbengine.h     |  2 ++
 src/plugins/debugger/idebuggerengine.h   |  1 +
 8 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h
index b8a60faba9f..364cb65176d 100644
--- a/src/plugins/debugger/debuggeractions.h
+++ b/src/plugins/debugger/debuggeractions.h
@@ -154,6 +154,7 @@ struct DebuggerManagerActions
     QAction *runToFunctionAction;
     QAction *jumpToLineAction1; // in the Debug menu
     QAction *jumpToLineAction2; // in the text editor context menu
+    QAction *returnFromFunctionAction;
     QAction *nextAction;
     QAction *snapshotAction;
     QAction *watchAction1; // in the Debug menu
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index 9b6cdb636c7..94c3aef9872 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -53,9 +53,11 @@ const char * const C_GDBDEBUGGER        = "Gdb Debugger";
 const char * const GDBRUNNING           = "Gdb.Running";
 
 const char * const DEBUGGER_COMMON_SETTINGS_ID = "A.Common";
-const char * const DEBUGGER_COMMON_SETTINGS_NAME = QT_TRANSLATE_NOOP("Debugger", "Common");
+const char * const DEBUGGER_COMMON_SETTINGS_NAME =
+    QT_TRANSLATE_NOOP("Debugger", "Common");
 const char * const DEBUGGER_SETTINGS_CATEGORY = "O.Debugger";
-const char * const DEBUGGER_SETTINGS_TR_CATEGORY = QT_TRANSLATE_NOOP("Debugger", "Debugger");
+const char * const DEBUGGER_SETTINGS_TR_CATEGORY =
+    QT_TRANSLATE_NOOP("Debugger", "Debugger");
 
 namespace Internal {
     enum { debug = 0 };
@@ -65,9 +67,10 @@ namespace Internal {
     const char * const LD_PRELOAD_ENV_VAR = "LD_PRELOAD";
 #endif
 
-}
+} // namespace Internal
 } // namespace Constants
 
+
 enum DebuggerState
 {
     DebuggerNotReady,          // Debugger not started
@@ -121,6 +124,7 @@ enum DebuggerCapabilities
     ReloadModuleCapability = 0x80,
     ReloadModuleSymbolsCapability = 0x100,
     BreakOnThrowAndCatchCapability = 0x200,
+    ReturnFromFunctionCapability = 0x400,
 };
 
 enum LogChannel
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index 06fad14ba01..eb2936ff98b 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -485,7 +485,11 @@ void DebuggerManager::init()
     d->m_actions.runToLineAction1 = new QAction(tr("Run to Line"), this);
     d->m_actions.runToLineAction2 = new QAction(tr("Run to Line"), this);
 
-    d->m_actions.runToFunctionAction = new QAction(tr("Run to Outermost Function"), this);
+    d->m_actions.runToFunctionAction =
+        new QAction(tr("Run to Outermost Function"), this);
+
+    d->m_actions.returnFromFunctionAction =
+        new QAction(tr("Immediately Return From Inner Function"), this);
 
     d->m_actions.jumpToLineAction1 = new QAction(tr("Jump to Line"), this);
     d->m_actions.jumpToLineAction2 = new QAction(tr("Jump to Line"), this);
@@ -524,6 +528,8 @@ void DebuggerManager::init()
         this, SLOT(jumpToLineExec()));
     connect(d->m_actions.jumpToLineAction2, SIGNAL(triggered()),
         this, SLOT(jumpToLineExec()));
+    connect(d->m_actions.returnFromFunctionAction, SIGNAL(triggered()),
+        this, SLOT(returnExec()));
     connect(d->m_actions.watchAction1, SIGNAL(triggered()),
         this, SLOT(addToWatchWindow()));
     connect(d->m_actions.watchAction2, SIGNAL(triggered()),
@@ -1185,6 +1191,13 @@ void DebuggerManager::nextExec()
         d->m_engine->nextExec();
 }
 
+void DebuggerManager::returnExec()
+{
+    QTC_ASSERT(d->m_engine, return);
+    resetLocation();
+    d->m_engine->returnExec();
+}
+
 void DebuggerManager::watchPoint()
 {
     if (QAction *action = qobject_cast<QAction *>(sender()))
@@ -1742,8 +1755,8 @@ void DebuggerManager::setState(DebuggerState state, bool forced)
     d->m_actions.watchAction1->setEnabled(true);
     d->m_actions.watchAction2->setEnabled(true);
     d->m_actions.breakAction->setEnabled(true);
-    d->m_actions.snapshotAction->setEnabled(
-        stopped && (engineCapabilities & SnapshotCapability));
+    d->m_actions.snapshotAction->
+        setEnabled(stopped && (engineCapabilities & SnapshotCapability));
 
     const bool interruptIsExit = !running;
     if (interruptIsExit) {
@@ -1762,6 +1775,8 @@ void DebuggerManager::setState(DebuggerState state, bool forced)
     d->m_actions.runToLineAction1->setEnabled(stopped);
     d->m_actions.runToLineAction2->setEnabled(stopped);
     d->m_actions.runToFunctionAction->setEnabled(stopped);
+    d->m_actions.returnFromFunctionAction->
+        setEnabled(stopped && (engineCapabilities & ReturnFromFunctionCapability));
 
     const bool canJump = stopped && (engineCapabilities & JumpToLineCapability);
     d->m_actions.jumpToLineAction1->setEnabled(canJump);
diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h
index 55f03a055f6..9912221fdd0 100644
--- a/src/plugins/debugger/debuggermanager.h
+++ b/src/plugins/debugger/debuggermanager.h
@@ -235,6 +235,7 @@ public slots:
     void stepOutExec();
     void nextExec();
     void continueExec();
+    void returnExec();
     void detachDebugger();
     void makeSnapshot();
 
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 67788f74ed9..8c0358323b5 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -119,6 +119,7 @@ const char * const RUN_TO_LINE2         = "Debugger.RunToLine2";
 const char * const RUN_TO_FUNCTION      = "Debugger.RunToFunction";
 const char * const JUMP_TO_LINE1        = "Debugger.JumpToLine1";
 const char * const JUMP_TO_LINE2        = "Debugger.JumpToLine2";
+const char * const RETURN_FROM_FUNCTION = "Debugger.ReturnFromFunction";
 const char * const SNAPSHOT             = "Debugger.Snapshot";
 const char * const TOGGLE_BREAK         = "Debugger.ToggleBreak";
 const char * const BREAK_BY_FUNCTION    = "Debugger.BreakByFunction";
@@ -799,6 +800,10 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
         Constants::JUMP_TO_LINE1, debuggercontext);
     mdebug->addAction(cmd);
 
+    cmd = am->registerAction(actions.returnFromFunctionAction,
+        Constants::RETURN_FROM_FUNCTION, debuggercontext);
+    mdebug->addAction(cmd);
+
 #ifdef USE_REVERSE_DEBUGGING
     cmd = am->registerAction(actions.reverseDirectionAction,
         Constants::REVERSE, debuggercontext);
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 0947340b925..27777a29e73 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1711,7 +1711,8 @@ unsigned GdbEngine::debuggerCapabilities() const
         | AutoDerefPointersCapability | DisassemblerCapability
         | RegisterCapability | ShowMemoryCapability
         | JumpToLineCapability | ReloadModuleCapability
-        | ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability;
+        | ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability
+        | ReturnFromFunctionCapability;
 }
 
 void GdbEngine::continueInferiorInternal()
@@ -1902,6 +1903,21 @@ void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber)
 #endif
 }
 
+void GdbEngine::returnExec()
+{
+    QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
+    setTokenBarrier();
+    setState(InferiorRunningRequested);
+    showStatusMessage(tr("Immediate return from function requested..."), 5000);
+    postCommand("-exec-finish", RunRequest, CB(handleExecReturn));
+}
+
+void GdbEngine::handleExecReturn(const GdbResponse &response)
+{
+    if (response.resultClass == GdbResultDone) {
+        updateAll();
+    }
+}
 /*!
     \fn void GdbEngine::setTokenBarrier()
     \brief Discard the results of all pending watch-updating commands.
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 1c127a5dbb5..479a6d64b3e 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -296,10 +296,12 @@ private: ////////// Inferior Management //////////
     virtual void runToFunctionExec(const QString &functionName);
 //    void handleExecRunToFunction(const GdbResponse &response);
     virtual void jumpToLineExec(const QString &fileName, int lineNumber);
+    virtual void returnExec();
 
     void handleExecContinue(const GdbResponse &response);
     void handleExecStep(const GdbResponse &response);
     void handleExecNext(const GdbResponse &response);
+    void handleExecReturn(const GdbResponse &response);
 
     qint64 inferiorPid() const { return m_manager->inferiorPid(); }
     void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); }
diff --git a/src/plugins/debugger/idebuggerengine.h b/src/plugins/debugger/idebuggerengine.h
index b60e8c7fb34..6409ae5cb95 100644
--- a/src/plugins/debugger/idebuggerengine.h
+++ b/src/plugins/debugger/idebuggerengine.h
@@ -82,6 +82,7 @@ public:
     virtual void nextExec() = 0;
     virtual void stepIExec() = 0;
     virtual void nextIExec() = 0;
+    virtual void returnExec() {}
 
     virtual void continueInferior() = 0;
     virtual void interruptInferior() = 0;
-- 
GitLab