Commit 25ee70bb authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Debugger: Use the code model to detect unitialized variables.



This should save debugger round trips and crashes in the debugging
helpers.
Add respective option to debugging helper option page, defaulting to
true.On this occasion, make CDB detect shadowed variables correctly
and display them as "<shadowed n>" as does the Gdb engine by
reversing the direction in which
CdbSymbolGroupContext::populateINameIndexMap works.
Rubber-stamped-by: default avatarhjk <qtc-committer@nokia.com>
parent c79476e7
......@@ -341,6 +341,8 @@ void CdbDumperInitThread ::run()
CdbDumperHelper::CdbDumperHelper(DebuggerManager *manager,
CdbComInterfaces *cif) :
m_tryInjectLoad(true),
m_msgDisabled(QLatin1String("Dumpers are disabled")),
m_msgNotInScope(QLatin1String("Data not in scope")),
m_state(NotLoaded),
m_manager(manager),
m_cif(cif),
......@@ -648,8 +650,12 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpTypeI(const WatchData &wd, bool
{
errorMessage->clear();
// Check failure cache and supported types
if (m_state == Disabled) {
*errorMessage = QLatin1String("Dumpers are disabled");
if (m_state == Disabled) {
*errorMessage =m_msgDisabled;
return DumpNotHandled;
}
if (wd.error) {
*errorMessage =m_msgNotInScope;
return DumpNotHandled;
}
if (m_failedTypes.contains(wd.type)) {
......
......@@ -134,6 +134,8 @@ private:
static bool writeToDebuggee(CIDebugDataSpaces *ds, const QByteArray &buffer, quint64 address, QString *errorMessage);
const bool m_tryInjectLoad;
const QString m_msgDisabled;
const QString m_msgNotInScope;
State m_state;
DebuggerManager *m_manager;
CdbComInterfaces *m_cif;
......
......@@ -217,7 +217,7 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
bool handled = false;
do {
if (!isPointerType(wd.type))
if (wd.error || !isPointerType(wd.type))
break;
const int classPos = wd.value.indexOf(" class ");
if (classPos == -1)
......@@ -396,9 +396,9 @@ bool CdbStackFrameContext::editorToolTip(const QString &iname,
*errorMessage = QString::fromLatin1("%1 not found.").arg(iname);
return false;
}
const WatchData wd = m_symbolContext->symbolAt(index);
// Check dumpers. Should actually be just one item.
if (m_useDumpers && m_dumper->state() != CdbDumperHelper::Disabled) {
const WatchData wd = m_symbolContext->watchDataAt(index);
if (m_useDumpers && !wd.error && m_dumper->state() != CdbDumperHelper::Disabled) {
QList<WatchData> result;
if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, &result, errorMessage)) {
foreach (const WatchData &dwd, result) {
......
......@@ -33,8 +33,11 @@
#include "cdbsymbolgroupcontext.h"
#include "cdbdebugengine_p.h"
#include "cdbdumperhelper.h"
#include "debuggeractions.h"
#include "debuggermanager.h"
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
namespace Debugger {
......@@ -160,7 +163,13 @@ CdbStackFrameContext *CdbStackTraceContext::frameContextAt(int index, QString *e
*errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
return 0;
}
CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(QLatin1String("local"), sg, errorMessage);
// Exclude unitialized variables if desired
QStringList uninitializedVariables;
if (theDebuggerAction(UseCodeModel)->isChecked()) {
const StackFrame &frame = m_frames.at(index);
getUninitializedVariables(DebuggerManager::instance()->cppCodeModelSnapshot(), frame.function, frame.file, frame.line, &uninitializedVariables);
}
CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(QLatin1String("local"), sg, uninitializedVariables, errorMessage);
if (!sc) {
*errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
return 0;
......
......@@ -39,6 +39,9 @@
enum { debug = 0 };
enum { debugInternalDumpers = 0 };
// name separator for shadowed variables
static const char iNameShadowDelimiter = '#';
static inline QString msgSymbolNotFound(const QString &s)
{
return QString::fromLatin1("The symbol '%1' could not be found.").arg(s);
......@@ -83,6 +86,14 @@ QTextStream &operator<<(QTextStream &str, const DEBUG_SYMBOL_PARAMETERS &p)
return str;
}
static inline QString hexSymbolOffset(CIDebugSymbolGroup *sg, unsigned long index)
{
ULONG64 rc = 0;
if (FAILED(sg->GetSymbolOffset(index, &rc)))
rc = 0;
return QLatin1String("0x") + QString::number(rc, 16);
}
// A helper function to extract a string value from a member function of
// IDebugSymbolGroup2 taking the symbol index and a character buffer.
// Pass in the the member function as '&IDebugSymbolGroup2::GetSymbolNameWide'
......@@ -129,12 +140,15 @@ static inline CdbSymbolGroupContext::SymbolState getSymbolState(const DEBUG_SYMB
}
CdbSymbolGroupContext::CdbSymbolGroupContext(const QString &prefix,
CIDebugSymbolGroup *symbolGroup) :
CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables) :
m_prefix(prefix),
m_nameDelimiter(QLatin1Char('.')),
m_uninitializedVariables(uninitializedVariables.toSet()),
m_symbolGroup(symbolGroup),
m_unnamedSymbolNumber(1)
{
}
CdbSymbolGroupContext::~CdbSymbolGroupContext()
......@@ -144,9 +158,10 @@ CdbSymbolGroupContext::~CdbSymbolGroupContext()
CdbSymbolGroupContext *CdbSymbolGroupContext::create(const QString &prefix,
CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables,
QString *errorMessage)
{
CdbSymbolGroupContext *rc = new CdbSymbolGroupContext(prefix, symbolGroup);
CdbSymbolGroupContext *rc = new CdbSymbolGroupContext(prefix, symbolGroup, uninitializedVariables);
if (!rc->init(errorMessage)) {
delete rc;
return 0;
......@@ -173,28 +188,36 @@ bool CdbSymbolGroupContext::init(QString *errorMessage)
*errorMessage = QString::fromLatin1("In %1: %2 (%3 symbols)").arg(QLatin1String(Q_FUNC_INFO), msgComFailed("GetSymbolParameters", hr)).arg(count);
return false;
}
populateINameIndexMap(m_prefix, DEBUG_ANY_ID, 0, count);
populateINameIndexMap(m_prefix, DEBUG_ANY_ID, count);
}
if (debug)
qDebug() << Q_FUNC_INFO << '\n'<< toString();
qDebug() << Q_FUNC_INFO << '\n'<< toString(true);
return true;
}
/* Make the entries for iname->index mapping. We might encounter
* already expanded subitems when doing it for top-level ('this'-pointers),
* recurse in that case, (skip over expanded children).
* Loop backwards to detect shadowed variables in the order the
/* debugger expects them:
\code
int x; // Occurrence (1), should be reported as "x <shadowed 1>"
if (true) {
int x = 5; (2) // Occurrence (2), should be reported as "x"
}
\endcode
* The order in the symbol group is (1),(2). Give them an iname of
* <root>#<shadowed-nr>, which will be split apart for display. */
void CdbSymbolGroupContext::populateINameIndexMap(const QString &prefix, unsigned long parentId,
unsigned long start, unsigned long count)
unsigned long end)
{
// Make the entries for iname->index mapping. We might encounter
// already expanded subitems when doing it for top-level, recurse in that case.
const QString symbolPrefix = prefix + m_nameDelimiter;
if (debug)
qDebug() << Q_FUNC_INFO << '\n'<< symbolPrefix << start << count;
const unsigned long end = m_symbolParameters.size();
unsigned long seenChildren = 0;
// Skip over expanded children
for (unsigned long i = start; i < end && seenChildren < count; i++) {
qDebug() << Q_FUNC_INFO << '\n'<< symbolPrefix << parentId << end;
for (unsigned long i = end - 1; ; i--) {
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(i);
if (parentId == p.ParentSymbol) {
seenChildren++;
// "__formal" occurs when someone writes "void foo(int /* x */)..."
static const QString unnamedFormalParameter = QLatin1String("__formal");
QString symbolName = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i);
......@@ -203,11 +226,21 @@ void CdbSymbolGroupContext::populateINameIndexMap(const QString &prefix, unsigne
symbolName += QString::number(m_unnamedSymbolNumber++);
symbolName += QLatin1Char('>');
}
const QString name = symbolPrefix + symbolName;
// Find a unique name in case the variable is shadowed by
// an existing one
const QString namePrefix = symbolPrefix + symbolName;
QString name = namePrefix;
for (int n = 1; m_inameIndexMap.contains(name); n++) {
name.truncate(namePrefix.size());
name += QLatin1Char(iNameShadowDelimiter);
name += QString::number(n);
}
m_inameIndexMap.insert(name, i);
if (getSymbolState(p) == ExpandedSymbol)
populateINameIndexMap(name, i, i + 1, p.SubElements);
populateINameIndexMap(name, i, i + 1 + p.SubElements);
}
if (i == 0 || i == parentId)
break;
}
}
......@@ -223,7 +256,10 @@ QString CdbSymbolGroupContext::toString(bool verbose) const
str << " ";
str << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i);
if (p.Flags & DEBUG_SYMBOL_IS_LOCAL)
str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, i);
str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, i) << '\'';
str << " Address: " << hexSymbolOffset(m_symbolGroup, i);
if (verbose)
str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, i) << '\'';
str << p << '\n';
}
if (verbose) {
......@@ -348,7 +384,7 @@ bool CdbSymbolGroupContext::expandSymbol(const QString &prefix, unsigned long in
if (it.value() > index)
it.value() += newSymbolCount;
// insert the new symbols
populateINameIndexMap(prefix, index, index + 1, newSymbolCount);
populateINameIndexMap(prefix, index, index + 1 + newSymbolCount);
if (debug > 1)
qDebug() << '<' << Q_FUNC_INFO << '\n' << prefix << index << '\n' << toString();
return true;
......@@ -365,14 +401,6 @@ QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const
return m_inameIndexMap.key(index);
}
static inline QString hexSymbolOffset(CIDebugSymbolGroup *sg, unsigned long index)
{
ULONG64 rc = 0;
if (FAILED(sg->GetSymbolOffset(index, &rc)))
rc = 0;
return QLatin1String("0x") + QString::number(rc, 16);
}
// check for "0x000", "0x000 class X"
static inline bool isNullPointer(const WatchData &wd)
{
......@@ -409,19 +437,35 @@ static inline QString fixValue(const QString &value)
return removeInnerTemplateType(value);
}
WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const
{
WatchData wd;
wd.iname = symbolINameAt(index);
wd.exp = wd.iname;
// Determine name from iname and format shadowed variables correctly
// as "<shadowed X>, see populateINameIndexMap().
const int lastDelimiterPos = wd.iname.lastIndexOf(m_nameDelimiter);
QString name = lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1);
int shadowedNumber = 0;
const int shadowedPos = name.lastIndexOf(QLatin1Char(iNameShadowDelimiter));
if (shadowedPos != -1) {
shadowedNumber = name.mid(shadowedPos + 1).toInt();
name.truncate(shadowedPos);
}
// For class hierarchies, we get sometimes complicated std::template types here.
// Remove them for display
wd.name = removeInnerTemplateType(lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1));
// (std::map extends std::tree<>... Remove them for display only.
const QString fullShadowedName = WatchData::shadowedName(name, shadowedNumber);
wd.name = WatchData::shadowedName(removeInnerTemplateType(name), shadowedNumber);
wd.addr = hexSymbolOffset(m_symbolGroup, index);
const QString type = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, index);
const QString type = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, index);
wd.setType(type);
// Check for unitialized variables at level 0 only.
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(index);
if (p.ParentSymbol == DEBUG_ANY_ID && m_uninitializedVariables.contains(fullShadowedName)) {
wd.setError(WatchData::msgNotInScope());
return wd;
}
const QString value = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
wd.setType(type);
wd.setValue(fixValue(value));
wd.setChildrenNeeded(); // compensate side effects of above setters
// Figure out children. The SubElement is only a guess unless the symbol,
......@@ -429,7 +473,7 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
// If the symbol has children (expanded or not), we leave the 'Children' flag
// in 'needed' state. Suppress 0-pointers right ("0x000 class X")
// here as they only lead to children with memory access errors.
const bool hasChildren = m_symbolParameters.at(index).SubElements && !isNullPointer(wd);
const bool hasChildren = p.SubElements && !isNullPointer(wd);
wd.setHasChildren(hasChildren);
if (debug > 1)
qDebug() << Q_FUNC_INFO << index << '\n' << wd.toString();
......@@ -438,7 +482,7 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
WatchData CdbSymbolGroupContext::dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index)
{
WatchData rc = symbolAt(index);
WatchData rc = watchDataAt(index);
dump(ds, &rc);
return rc;
}
......
......@@ -69,12 +69,14 @@ class CdbSymbolGroupContext
{
Q_DISABLE_COPY(CdbSymbolGroupContext);
explicit CdbSymbolGroupContext(const QString &prefix,
CIDebugSymbolGroup *symbolGroup);
CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables = QStringList());
public:
~CdbSymbolGroupContext();
static CdbSymbolGroupContext *create(const QString &prefix,
static CdbSymbolGroupContext *create(const QString &prefix,
CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables,
QString *errorMessage);
QString prefix() const { return m_prefix; }
......@@ -118,7 +120,7 @@ public:
int dumpedOwner,
OutputIterator it, QString *errorMessage);
WatchData symbolAt(unsigned long index) const;
WatchData watchDataAt(unsigned long index) const;
// Run the internal dumpers on the symbol
WatchData dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index);
......@@ -155,7 +157,7 @@ private:
unsigned long *parentId,
QString *errorMessage);
bool expandSymbol(const QString &prefix, unsigned long index, QString *errorMessage);
void populateINameIndexMap(const QString &prefix, unsigned long parentId, unsigned long start, unsigned long count);
void populateINameIndexMap(const QString &prefix, unsigned long parentId, unsigned long end);
QString symbolINameAt(unsigned long index) const;
int dumpQString(CIDebugDataSpaces *ds, WatchData *wd);
......@@ -166,6 +168,7 @@ private:
const QString m_prefix;
const QChar m_nameDelimiter;
const QSet<QString> m_uninitializedVariables;
CIDebugSymbolGroup *m_symbolGroup;
NameIndexMap m_inameIndexMap;
......
......@@ -61,7 +61,7 @@ bool CdbSymbolGroupContext::getDumpChildSymbols(CIDebugDataSpaces *ds, const QSt
for (int s = start; s < m_symbolParameters.size(); ++s) {
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(s);
if (p.ParentSymbol == parentId && isSymbolDisplayable(p)) {
WatchData wd = symbolAt(s);
WatchData wd = watchDataAt(s);
// Run internal dumper, mark ownership
if (ds) {
switch (dump(ds, &wd)) {
......
......@@ -229,6 +229,13 @@ DebuggerSettings *DebuggerSettings::instance()
item->setValue(false);
instance->insertItem(DebugDebuggingHelpers, item);
item = new SavedAction(instance);
item->setSettingsKey(debugModeGroup, QLatin1String("UseCodeModel"));
item->setText(tr("Use code model"));
item->setCheckable(true);
item->setDefaultValue(false);
item->setValue(false);
instance->insertItem(UseCodeModel, item);
item = new SavedAction(instance);
item->setText(tr("Recheck debugging helper availability"));
......
......@@ -85,6 +85,8 @@ enum DebuggerActionCode
UseCustomDebuggingHelperLocation,
CustomDebuggingHelperLocation,
DebugDebuggingHelpers,
UseCodeModel,
UseToolTipsInMainEditor,
UseToolTipsInLocalsView,
......
......@@ -61,6 +61,8 @@
#include <utils/qtcassert.h>
#include <utils/fancymainwindow.h>
#include <projectexplorer/toolchain.h>
#include <cplusplus/CppDocument.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <QtCore/QDebug>
#include <QtCore/QDir>
......@@ -303,6 +305,8 @@ struct DebuggerManagerPrivate
IDebuggerEngine *m_engine;
DebuggerState m_state;
CPlusPlus::Snapshot m_codeModelSnapshot;
};
DebuggerManager *DebuggerManagerPrivate::instance = 0;
......@@ -623,6 +627,18 @@ WatchHandler *DebuggerManager::watchHandler() const
return d->m_watchHandler;
}
const CPlusPlus::Snapshot &DebuggerManager::cppCodeModelSnapshot() const
{
if (d->m_codeModelSnapshot.isEmpty() && theDebuggerAction(UseCodeModel)->isChecked())
d->m_codeModelSnapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
return d->m_codeModelSnapshot;
}
void DebuggerManager::clearCppCodeModelSnapshot()
{
d->m_codeModelSnapshot.clear();
}
SourceFilesWindow *DebuggerManager::sourceFileWindow() const
{
return d->m_sourceFilesWindow;
......@@ -1026,6 +1042,7 @@ void DebuggerManager::exitDebugger()
// in turn will handle the cleanup.
if (d->m_engine && state() != DebuggerNotReady)
d->m_engine->exitDebugger();
d->m_codeModelSnapshot.clear();
}
DebuggerStartParametersPtr DebuggerManager::startParameters() const
......
......@@ -59,6 +59,10 @@ namespace TextEditor {
class ITextEditor;
}
namespace CPlusPlus {
class Snapshot;
}
namespace Debugger {
namespace Internal {
......@@ -180,6 +184,8 @@ public:
QString *settingsCategory = 0,
QString *settingsPage = 0) const;
const CPlusPlus::Snapshot &cppCodeModelSnapshot() const;
static DebuggerManager *instance();
public slots:
......@@ -232,6 +238,7 @@ public slots:
void setRegisterValue(int nr, const QString &value);
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
void clearCppCodeModelSnapshot();
public slots: // FIXME
void showDebuggerOutput(const QString &msg)
......@@ -267,7 +274,8 @@ private:
Internal::ThreadsHandler *threadsHandler() const;
Internal::WatchHandler *watchHandler() const;
Internal::SourceFilesWindow *sourceFileWindow() const;
QWidget *threadsWindow() const;
QWidget *threadsWindow() const;
Internal::DebuggerManagerActions debuggerManagerActions() const;
void notifyInferiorStopped();
......
......@@ -373,6 +373,9 @@ QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation),
m_ui.dumperLocationChooser);
m_group.insert(theDebuggerAction(UseCodeModel),
m_ui.checkBoxUseCodeModel);
#ifdef QT_DEBUG
m_group.insert(theDebuggerAction(DebugDebuggingHelpers),
m_ui.checkBoxDebugDebuggingHelpers);
......
......@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>403</width>
<width>432</width>
<height>434</height>
</rect>
</property>
......@@ -83,10 +83,20 @@
</widget>
</item>
<item>
<widget class="Utils::PathChooser" name="dumperLocationChooser" native="true"/>
<widget class="Utils::PathChooser" name="dumperLocationChooser"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxUseCodeModel">
<property name="toolTip">
<string>Makes use of Qt Creator's code model to find out if a variable has already been assigned a value at the point the debugger interrupts.</string>
</property>
<property name="text">
<string>Use code model</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxDebugDebuggingHelpers">
<property name="toolTip">
......
......@@ -89,10 +89,6 @@
#endif
#include <ctype.h>
// FIXME: temporary hack to evalaute tbreak based step-over behaviour
static QString lastFile;
static int lastLine;
namespace Debugger {
namespace Internal {
......@@ -1233,9 +1229,9 @@ void GdbEngine::handleStop2(const GdbResponse &response)
void GdbEngine::handleStop2(const GdbMi &data)
{
// Sometimes we get some interesting extra information. Grab it.
GdbMi frame = data.findChild("frame");
GdbMi shortName = frame.findChild("file");
GdbMi fullName = frame.findChild("fullname");
const GdbMi gdbmiFrame = data.findChild("frame");
GdbMi shortName = gdbmiFrame.findChild("file");
GdbMi fullName = gdbmiFrame.findChild("fullname");
if (shortName.isValid() && fullName.isValid()) {
QString file = QFile::decodeName(shortName.data());
QString full = QFile::decodeName(fullName.data());
......@@ -1246,16 +1242,17 @@ void GdbEngine::handleStop2(const GdbMi &data)
}
// Quick shot: Jump to stack frame #0.
if (frame.isValid()) {
const StackFrame f = parseStackFrame(frame, 0);
gotoLocation(f, true);
StackFrame frame;
if (gdbmiFrame.isValid()) {
frame = parseStackFrame(gdbmiFrame, 0);
gotoLocation(frame, true);
}
//
// Stack
//
manager()->stackHandler()->setCurrentIndex(0);
updateLocals(); // Quick shot
updateLocals(qVariantFromValue(frame)); // Quick shot
reloadStack(false);
......@@ -2583,11 +2580,6 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos,
//
//////////////////////////////////////////////////////////////////////
//: Variable
static const QString strNotInScope =
QCoreApplication::translate("Debugger::Internal::GdbEngine", "<not in scope>");
static void setWatchDataValue(WatchData &data, const GdbMi &mi,
int encoding = 0)
{
......@@ -2804,8 +2796,8 @@ void GdbEngine::updateSubItem(const WatchData &data0)
qDebug() << "FIXME: GdbEngine::updateSubItem:"
<< data.toString() << "should not happen";
#else
data.setType(strNotInScope);
data.setValue(strNotInScope);
data.setType(WatchData::msgNotInScope());
data.setValue(WatchData::msgNotInScope());
data.setHasChildren(false);
insertData(data);
return;
......@@ -3139,7 +3131,7 @@ void GdbEngine::handleVarCreate(const GdbResponse &response)
} else {
data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data()));
if (data.isWatcher()) {
data.value = strNotInScope;
data.value = WatchData::msgNotInScope();
data.type = _(" ");
data.setAllUnneeded();
data.setHasChildren(false);
......@@ -3213,7 +3205,7 @@ void GdbEngine::handleDebuggingHelperValue2(const GdbResponse &response)
GdbMi contents;
if (!parseConsoleStream(response, &contents)) {
data.setError(strNotInScope);
data.setError(WatchData::msgNotInScope());
insertData(data);
return;
}
......@@ -3306,7 +3298,7 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response)
// << " STREAM:" << out;
if (list.isEmpty()) {
//: Value for variable
data.setError(strNotInScope);