forked from qt-creator/qt-creator
Debugger[CDB]: Work on Qt 5 types.
Task-number: QTCREATORBUG-5475 Change-Id: Ic034f0f73a9dc375751dcb7dc463786ba596bec9 Reviewed-on: http://codereview.qt.nokia.com/2296 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
@@ -633,7 +633,11 @@ std::string widgetAt(const SymbolGroupValueContext &ctx, int x, int y, std::stri
|
||||
typedef SymbolGroupValue::SymbolList SymbolList;
|
||||
// First, resolve symbol since there are ambiguities. Take the first one which is the
|
||||
// overload for (int,int) and call by address instead off name to overcome that.
|
||||
const std::string func = QtInfo::get(ctx).prependQtGuiModule("QApplication::widgetAt");
|
||||
const QtInfo &qtInfo = QtInfo::get(ctx);
|
||||
const std::string func =
|
||||
qtInfo.prependQtModule("QApplication::widgetAt",
|
||||
qtInfo.version >= 5 && QtInfo::qt5WidgetSplit ?
|
||||
QtInfo::Widgets : QtInfo::Gui);
|
||||
const SymbolList symbols = SymbolGroupValue::resolveSymbol(func.c_str(), ctx, errorMessage);
|
||||
if (symbols.empty())
|
||||
return std::string(); // Not a gui application, likely
|
||||
|
||||
@@ -75,8 +75,9 @@ enum KnownType
|
||||
KT_QBasicAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 18,
|
||||
KT_QAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 19,
|
||||
KT_QObject = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 20,
|
||||
KT_QWidget = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 21,
|
||||
KT_QSharedPointer = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 22,
|
||||
KT_QWindow = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 21,
|
||||
KT_QWidget = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 22,
|
||||
KT_QSharedPointer = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 23,
|
||||
// Types: Various QT movable types
|
||||
KT_QPen = KT_Qt_Type + KT_Qt_MovableType + 30,
|
||||
KT_QUrl = KT_Qt_Type + KT_Qt_MovableType + 31 + KT_HasSimpleDumper,
|
||||
|
||||
@@ -624,38 +624,23 @@ static inline std::string resolveQtSymbol(const char *symbolC,
|
||||
|
||||
const QtInfo &QtInfo::get(const SymbolGroupValueContext &ctx)
|
||||
{
|
||||
static const char qtCoreDefaultModule[] = "QtCored";
|
||||
static const char qtGuiDefaultModule[] = "QtGuid";
|
||||
static const char qtNetworkDefaultModule[] = "QtNetworkd";
|
||||
static const char qtScriptDefaultModule[] = "QtScriptd";
|
||||
static QtInfo rc;
|
||||
if (!rc.coreModule.empty())
|
||||
if (!rc.libInfix.empty())
|
||||
return rc;
|
||||
|
||||
do {
|
||||
// Lookup qstrdup() to hopefully get module (potential libinfix) and namespace
|
||||
// Typically, this resolves to 'QtGuid4!qstrdup' and 'QtCored4!qstrdup'...
|
||||
const std::string qualifiedSymbol = resolveQtSymbol("qstrdup", qtCoreDefaultModule, "Core", ctx);
|
||||
const std::string qualifiedSymbol = resolveQtSymbol("qstrdup", "QtCored", "Core", ctx);
|
||||
const std::string::size_type exclPos = qualifiedSymbol.find('!'); // Resolved: 'QtCored4!qstrdup'
|
||||
if (exclPos == std::string::npos) {
|
||||
const char defaultVersion = '4';
|
||||
rc.libInfix = "d4";
|
||||
rc.version = 4;
|
||||
rc.coreModule = qtCoreDefaultModule + defaultVersion;
|
||||
rc.guiModule = qtGuiDefaultModule + defaultVersion;
|
||||
rc.networkModule = qtNetworkDefaultModule + defaultVersion;
|
||||
rc.scriptModule = qtScriptDefaultModule + defaultVersion;
|
||||
break;
|
||||
}
|
||||
// Should be 'QtCored4!qstrdup'
|
||||
rc.coreModule = qualifiedSymbol.substr(0, exclPos);
|
||||
rc.libInfix = qualifiedSymbol.substr(6, exclPos - 6);
|
||||
rc.version = qualifiedSymbol.at(exclPos - 1) - '0';
|
||||
// Derive other module names 'QtXX<infix>d4'
|
||||
rc.guiModule = rc.coreModule;
|
||||
rc.guiModule.replace(0, 6, "QtGui");
|
||||
rc.networkModule = rc.coreModule;
|
||||
rc.networkModule.replace(0, 6, "QtNetwork");
|
||||
rc.scriptModule = rc.coreModule;
|
||||
rc.scriptModule.replace(0, 6, "QtScript");
|
||||
// Any namespace? 'QtCored4!nsp::qstrdup'
|
||||
const std::string::size_type nameSpaceStart = exclPos + 1;
|
||||
const std::string::size_type colonPos = qualifiedSymbol.find(':', nameSpaceStart);
|
||||
@@ -665,12 +650,23 @@ const QtInfo &QtInfo::get(const SymbolGroupValueContext &ctx)
|
||||
} while (false);
|
||||
rc.qObjectType = rc.prependQtCoreModule("QObject");
|
||||
rc.qObjectPrivateType = rc.prependQtCoreModule("QObjectPrivate");
|
||||
rc.qWidgetPrivateType = rc.prependQtGuiModule("QWidgetPrivate");
|
||||
rc.qWindowPrivateType = rc.prependQtGuiModule("QWindowPrivate");
|
||||
rc.qWidgetPrivateType =
|
||||
rc.prependQtModule("QWidgetPrivate",
|
||||
rc.version >= 5 && qt5WidgetSplit ? Widgets : Gui);
|
||||
if (SymbolGroupValue::verbose)
|
||||
DebugPrint() << rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::string QtInfo::moduleName(Module m) const
|
||||
{
|
||||
// Must match the enumeration
|
||||
static const char* modNames[] =
|
||||
{"QtCore", "QtGui", "QtWidgets", "QtNetwork", "QtScript" };
|
||||
return modNames[m] + libInfix;
|
||||
}
|
||||
|
||||
std::string QtInfo::prependModuleAndNameSpace(const std::string &type,
|
||||
const std::string &module,
|
||||
const std::string &aNameSpace)
|
||||
@@ -703,7 +699,7 @@ std::string QtInfo::prependModuleAndNameSpace(const std::string &type,
|
||||
std::ostream &operator<<(std::ostream &os, const QtInfo &i)
|
||||
{
|
||||
os << "Qt Info: Version: " << i.version << " Modules '"
|
||||
<< i.coreModule << "', '" << i.guiModule
|
||||
<< i.moduleName(QtInfo::Core) << "', '" << i.moduleName(QtInfo::Gui)
|
||||
<< "', Namespace='" << i.nameSpace
|
||||
<< "', types: " << i.qObjectType << ','
|
||||
<< i.qObjectPrivateType << ',' << i.qWidgetPrivateType;
|
||||
@@ -1144,6 +1140,8 @@ static KnownType knownClassTypeHelper(const std::string &type,
|
||||
return KT_QObject;
|
||||
if (!type.compare(qPos, 7, "QWidget"))
|
||||
return KT_QWidget;
|
||||
if (!type.compare(qPos, 7, "QWindow"))
|
||||
return KT_QWindow;
|
||||
if (!type.compare(qPos, 7, "QLocale"))
|
||||
return KT_QLocale;
|
||||
if (!type.compare(qPos, 7, "QMatrix"))
|
||||
@@ -1944,18 +1942,23 @@ static inline bool dumpQRectF(const SymbolGroupValue &v, std::wostream &str)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Dump the object name
|
||||
static inline bool dumpQWidget(const SymbolGroupValue &v, std::wostream &str, void **specialInfoIn = 0)
|
||||
/* Return a SymbolGroupValue containing the private class of
|
||||
* a type (multiple) derived from QObject and something else
|
||||
* (QWidget: QObject,QPaintDevice or QWindow: QObject,QSurface).
|
||||
* We get differing behaviour for pointers and values on stack.
|
||||
* For 'QWidget *', the base class QObject usually can be accessed
|
||||
* by name (past the vtable). When browsing class hierarchies (stack),
|
||||
* typically only the uninteresting QPaintDevice is seen. */
|
||||
|
||||
SymbolGroupValue qobjectDerivedPrivate(const SymbolGroupValue &v,
|
||||
const std::string &qwPrivateType,
|
||||
const QtInfo &qtInfo)
|
||||
{
|
||||
const QtInfo &qtInfo = QtInfo::get(v.context());
|
||||
const std::string &qwPrivateType = qtInfo.qWidgetPrivateType;
|
||||
// We get differing behaviour caused by multiple inheritance of QWidget from QObject,QPaintDevice:
|
||||
// For 'QWidget *', the base class QObject usually can be accessed (past the vtable).
|
||||
// When browsing class hierarchies, typically only the uninteresting QPaintDevice is seen.
|
||||
SymbolGroupValue qwPrivate;
|
||||
if (const SymbolGroupValue base = v[SymbolGroupValue::stripModuleFromType(qtInfo.qObjectType).c_str()])
|
||||
qwPrivate = base["d_ptr"]["d"].pointerTypeCast(qwPrivateType.c_str());
|
||||
if (!qwPrivate && !SymbolGroupValue::isPointerType(v.type())) {
|
||||
if (const SymbolGroupValue qwPrivate = base["d_ptr"]["d"].pointerTypeCast(qwPrivateType.c_str()))
|
||||
return qwPrivate;
|
||||
if (!SymbolGroupValue::isPointerType(v.type()))
|
||||
return SymbolGroupValue();
|
||||
// Class hierarchy: Using brute force, add new symbol based on that
|
||||
// QScopedPointer<Private> is basically a 'X *' (first member).
|
||||
std::string errorMessage;
|
||||
@@ -1964,9 +1967,19 @@ static inline bool dumpQWidget(const SymbolGroupValue &v, std::wostream &str, vo
|
||||
const std::string name = str.str();
|
||||
SymbolGroupNode *qwPrivateNode
|
||||
= v.node()->symbolGroup()->addSymbol(v.module(), name, std::string(), &errorMessage);
|
||||
qwPrivate = SymbolGroupValue(qwPrivateNode, v.context());
|
||||
}
|
||||
const SymbolGroupValue oName = qwPrivate[unsigned(0)]["objectName"]; // QWidgetPrivate inherits QObjectPrivate
|
||||
return SymbolGroupValue(qwPrivateNode, v.context());
|
||||
}
|
||||
|
||||
// Dump the object name
|
||||
static inline bool dumpQWidget(const SymbolGroupValue &v, std::wostream &str, void **specialInfoIn = 0)
|
||||
{
|
||||
const QtInfo &qtInfo = QtInfo::get(v.context());
|
||||
const SymbolGroupValue qwPrivate =
|
||||
qobjectDerivedPrivate(v, qtInfo.qWidgetPrivateType, qtInfo);
|
||||
if (!qwPrivate)
|
||||
return false;
|
||||
// QWidgetPrivate inherits QObjectPrivate
|
||||
const SymbolGroupValue oName = qwPrivate[unsigned(0)]["objectName"];
|
||||
if (!oName)
|
||||
return false;
|
||||
if (specialInfoIn)
|
||||
@@ -1990,6 +2003,24 @@ static inline bool dumpQObject(const SymbolGroupValue &v, std::wostream &str, vo
|
||||
return false;
|
||||
}
|
||||
|
||||
// Dump the object name
|
||||
static inline bool dumpQWindow(const SymbolGroupValue &v, std::wostream &str, void **specialInfoIn = 0)
|
||||
{
|
||||
const QtInfo &qtInfo = QtInfo::get(v.context());
|
||||
const SymbolGroupValue qwPrivate =
|
||||
qobjectDerivedPrivate(v, qtInfo.qWindowPrivateType, qtInfo);
|
||||
if (!qwPrivate)
|
||||
return false;
|
||||
// QWindowPrivate inherits QObjectPrivate
|
||||
const SymbolGroupValue oName = qwPrivate[unsigned(0)]["objectName"]; // QWidgetPrivate inherits QObjectPrivate
|
||||
if (!oName)
|
||||
return false;
|
||||
if (specialInfoIn)
|
||||
*specialInfoIn = qwPrivate.node();
|
||||
dumpQString(oName, str);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Dump a std::string.
|
||||
static bool dumpStd_W_String(const SymbolGroupValue &v, int type, std::wostream &str)
|
||||
{
|
||||
@@ -2357,6 +2388,9 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx,
|
||||
case KT_QWidget:
|
||||
rc = dumpQWidget(v, str, specialInfoIn) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
|
||||
break;
|
||||
case KT_QWindow:
|
||||
rc = dumpQWindow(v, str, specialInfoIn) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
|
||||
break;
|
||||
case KT_QSharedPointer:
|
||||
rc = dumpQSharedPointer(v, str, specialInfoIn) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
|
||||
break;
|
||||
@@ -2696,6 +2730,7 @@ std::vector<AbstractSymbolGroupNode *>
|
||||
rc = complexDumpQByteArray(n, ctx);
|
||||
break;
|
||||
case KT_QWidget: // Special info by simple dumper is the QWidgetPrivate node
|
||||
case KT_QWindow: // Special info by simple dumper is the QWindowPrivate node
|
||||
case KT_QObject: // Special info by simple dumper is the QObjectPrivate node
|
||||
if (specialInfo) {
|
||||
SymbolGroupNode *qObjectPrivateNode = reinterpret_cast<SymbolGroupNode *>(specialInfo);
|
||||
|
||||
@@ -171,20 +171,32 @@ std::ostream &operator<<(std::ostream &, const SymbolGroupValue &v);
|
||||
|
||||
struct QtInfo
|
||||
{
|
||||
enum { qt5WidgetSplit = 0 };
|
||||
|
||||
enum Module
|
||||
{
|
||||
Core, Gui, Widgets, Network, Script
|
||||
};
|
||||
|
||||
QtInfo() : version(0) {}
|
||||
|
||||
static const QtInfo &get(const SymbolGroupValueContext &ctx);
|
||||
|
||||
// Prepend core module and Qt namespace. To be able to work with some
|
||||
// 'complicated' types like QMapNode, specifying the module helps
|
||||
std::string prependQtModule(const std::string &type, Module m = Core) const
|
||||
{ return QtInfo::prependModuleAndNameSpace(type, moduleName(m), nameSpace); }
|
||||
|
||||
std::string prependQtCoreModule(const std::string &type) const
|
||||
{ return QtInfo::prependModuleAndNameSpace(type, coreModule, nameSpace); }
|
||||
{ return prependQtModule(type, Core); }
|
||||
std::string prependQtGuiModule(const std::string &type) const
|
||||
{ return QtInfo::prependModuleAndNameSpace(type, guiModule, nameSpace); }
|
||||
{ return QtInfo::prependQtModule(type, Gui); }
|
||||
std::string prependQtWidgetsModule(const std::string &type) const
|
||||
{ return QtInfo::prependQtModule(type, Widgets); }
|
||||
std::string prependQtNetworkModule(const std::string &type) const
|
||||
{ return QtInfo::prependModuleAndNameSpace(type, networkModule, nameSpace); }
|
||||
{ return QtInfo::prependQtModule(type, Network); }
|
||||
std::string prependQtScriptModule(const std::string &type) const
|
||||
{ return QtInfo::prependModuleAndNameSpace(type, scriptModule, nameSpace); }
|
||||
{ return QtInfo::prependQtModule(type, Script); }
|
||||
|
||||
// Prepend module and namespace if missing with some smartness
|
||||
// ('Foo' or -> 'nsp::Foo') => 'QtCored4!nsp::Foo'
|
||||
@@ -192,15 +204,15 @@ struct QtInfo
|
||||
const std::string &module,
|
||||
const std::string &nameSpace);
|
||||
|
||||
std::string moduleName(Module m) const;
|
||||
|
||||
int version;
|
||||
std::string nameSpace;
|
||||
std::string coreModule;
|
||||
std::string guiModule;
|
||||
std::string networkModule;
|
||||
std::string scriptModule;
|
||||
std::string libInfix;
|
||||
// Fully qualified types with module and namespace
|
||||
std::string qObjectType;
|
||||
std::string qObjectPrivateType;
|
||||
std::string qWindowPrivateType;
|
||||
std::string qWidgetPrivateType;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user