Commit 5139f513 authored by dt's avatar dt
Browse files

Merge branch 'master' of git@scm.dev.nokia.troll.no:creator/mainline

parents 660b210e 8f02d4da
......@@ -174,6 +174,9 @@ QT_BEGIN_NAMESPACE
struct Sender { QObject *sender; int signal; int ref; };
const char *stdStringTypeC = "std::basic_string<char,std::char_traits<char>,std::allocator<char> >";
const char *stdWideStringTypeUShortC = "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >";
#if QT_VERSION < 0x040600
struct Connection
{
......@@ -905,7 +908,8 @@ static inline void dumpChildNumChildren(QDumper &d, InnerValueResult innerValueR
}
}
static InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr,
// Called by templates, so, not static.
InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr,
const char *field = "value")
{
char buf[30];
......@@ -1017,13 +1021,13 @@ static InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, cons
return InnerValueNotHandled;
case 't':
if (isEqual(type, "std::string")
|| isEqual(type, "std::basic_string<char,std::char_traits<char>,std::allocator<char> >")) {
|| isEqual(type, stdStringTypeC)) {
d.putCommaIfNeeded();
dumpStdStringValue(d, *reinterpret_cast<const std::string*>(addr));
return InnerValueNoFurtherChildren;
}
if (isEqual(type, "std::wstring")
|| isEqual(type, "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >")) {
|| isEqual(type, stdWideStringTypeUShortC)) {
dumpStdWStringValue(d, *reinterpret_cast<const std::wstring*>(addr));
return InnerValueNoFurtherChildren;
}
......@@ -2905,9 +2909,16 @@ static void qDumpStdList(QDumper &d)
d.disarm();
}
static void qDumpStdMap(QDumper &d)
/* Dump out an arbitrary map. To iterate the map,
* it is cast to a map of <KeyType,Value>. 'int' can be used for both
* for all types if the implementation does not depend on the types
* which is the case for GNU STL. The implementation used by MS VC, however,
* does depend on the key/value type, so, special cases need to be hardcoded. */
template <class KeyType, class ValueType>
static void qDumpStdMapHelper(QDumper &d)
{
typedef std::map<int, int> DummyType;
typedef std::map<KeyType, ValueType> DummyType;
const DummyType &map = *reinterpret_cast<const DummyType*>(d.data);
const char *keyType = d.templateParameters[0];
const char *valueType = d.templateParameters[1];
......@@ -2915,14 +2926,15 @@ static void qDumpStdMap(QDumper &d)
qCheckAccess(p);
p = deref(p);
int nn = map.size();
const int nn = map.size();
if (nn < 0)
return;
DummyType::const_iterator it = map.begin();
for (int i = 0; i < nn && i < 10 && it != map.end(); ++i, ++it)
Q_TYPENAME DummyType::const_iterator it = map.begin();
const Q_TYPENAME DummyType::const_iterator cend = map.end();
for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)
qCheckAccess(it.operator->());
QByteArray strippedInnerType = stripPointerType(d.innertype);
const QByteArray strippedInnerType = stripPointerType(d.innertype);
d.putItem("numchild", nn);
d.putItemCount("value", nn);
d.putItem("valuedisabled", "true");
......@@ -2937,6 +2949,7 @@ static void qDumpStdMap(QDumper &d)
pairType[strlen(pairType) - 2] = 0;
d.putItem("pairtype", pairType);
InnerValueResult innerValueResult = InnerValueChildrenSpecified;
if (d.dumpChildren) {
bool isSimpleKey = isSimpleType(keyType);
bool isSimpleValue = isSimpleType(valueType);
......@@ -2951,12 +2964,12 @@ static void qDumpStdMap(QDumper &d)
d.beginChildren();
it = map.begin();
for (int i = 0; i < 1000 && it != map.end(); ++i, ++it) {
for (int i = 0; i < 1000 && it != cend; ++i, ++it) {
d.beginHash();
const void *node = it.operator->();
d.putItem("name", i);
qDumpInnerValueHelper(d, keyType, node, "key");
qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset));
innerValueResult = qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset));
if (isSimpleKey && isSimpleValue) {
d.putItem("type", valueType);
d.putItem("addr", addOffset(node, valueOffset));
......@@ -2972,22 +2985,61 @@ static void qDumpStdMap(QDumper &d)
d.putEllipsis();
d.endChildren();
}
dumpChildNumChildren(d, innerValueResult);
d.disarm();
}
static void qDumpStdSet(QDumper &d)
static void qDumpStdMap(QDumper &d)
{
#ifdef Q_CC_MSVC
// As the map implementation inherits from a base class
// depending on the key, use something equivalent to iterate it.
const int keySize = d.extraInt[0];
const int valueSize = d.extraInt[1];
if (keySize == valueSize) {
if (keySize == sizeof(int)) {
qDumpStdMapHelper<int,int>(d);
return;
}
if (keySize == sizeof(std::string)) {
qDumpStdMapHelper<std::string,std::string>(d);
return;
}
return;
}
if (keySize == sizeof(int) && valueSize == sizeof(std::string)) {
qDumpStdMapHelper<int,std::string>(d);
return;
}
if (keySize == sizeof(std::string) && valueSize == sizeof(int)) {
qDumpStdMapHelper<std::string,int>(d);
return;
}
#else
qDumpStdMapHelper<int,int>(d);
#endif
}
/* Dump out an arbitrary set. To iterate the set,
* it is cast to a set of <KeyType>. 'int' can be used
* for all types if the implementation does not depend on the key type
* which is the case for GNU STL. The implementation used by MS VC, however,
* does depend on the key type, so, special cases need to be hardcoded. */
template <class KeyType>
static void qDumpStdSetHelper(QDumper &d)
{
typedef std::set<int> DummyType;
typedef std::set<KeyType> DummyType;
const DummyType &set = *reinterpret_cast<const DummyType*>(d.data);
const void *p = d.data;
qCheckAccess(p);
p = deref(p);
int nn = set.size();
const int nn = set.size();
if (nn < 0)
return;
DummyType::const_iterator it = set.begin();
const DummyType::const_iterator cend = set.end();
Q_TYPENAME DummyType::const_iterator it = set.begin();
const Q_TYPENAME DummyType::const_iterator cend = set.end();
for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)
qCheckAccess(it.operator->());
......@@ -3024,6 +3076,29 @@ static void qDumpStdSet(QDumper &d)
d.disarm();
}
static void qDumpStdSet(QDumper &d)
{
#ifdef Q_CC_MSVC
// As the set implementation inherits from a base class
// depending on the key, use something equivalent to iterate it.
const int innerSize = d.extraInt[0];
if (innerSize == sizeof(int)) {
qDumpStdSetHelper<int>(d);
return;
}
if (innerSize == sizeof(std::string)) {
qDumpStdSetHelper<std::string>(d);
return;
}
if (innerSize == sizeof(std::wstring)) {
qDumpStdSetHelper<std::wstring>(d);
return;
}
#else
qDumpStdSetHelper<int>(d);
#endif
}
static void qDumpStdString(QDumper &d)
{
const std::string &str = *reinterpret_cast<const std::string *>(d.data);
......@@ -3329,12 +3404,37 @@ template <class Key, class Value>
d.put(keyType);
d.put(',');
d.put(valueType);
if (valueType[qstrlen(valueType) - 1] == '>')
d.put(' ');
d.put(">'*)0)->value=\"");
d.put(valueOffset);
d.put('"');
return d;
}
// Helper to write out common expression values for CDB:
// Offsets of a std::pair for dumping std::map node value which look like
// "(size_t)&(('std::pair<int const ,unsigned int>'*)0)->second"
template <class Key, class Value>
inline QDumper & putStdPairValueOffsetExpression(const char *keyType,
const char *valueType,
QDumper &d)
{
std::pair<Key, Value> *p = 0;
const int valueOffset = (char *)&(p->second) - (char*)p;
d.put("(size_t)&(('std::pair<");
d.put(keyType);
d.put(" const ,");
d.put(valueType);
if (valueType[qstrlen(valueType) - 1] == '>')
d.put(' ');
d.put(">'*)0)->second=\"");
d.put(valueOffset);
d.put('"');
return d;
}
extern "C" Q_DECL_EXPORT
void *qDumpObjectData440(
int protocolVersion,
......@@ -3461,7 +3561,18 @@ void *qDumpObjectData440(
putQMapNodeOffsetExpression<int,QVariant>("int", NS"QVariant", d).put(',');
putQMapNodeOffsetExpression<QString,int>(NS"QString", "int", d).put(',');
putQMapNodeOffsetExpression<QString,QString>(NS"QString", NS"QString", d).put(',');
putQMapNodeOffsetExpression<QString,QVariant>(NS"QString", NS"QVariant", d);
putQMapNodeOffsetExpression<QString,QVariant>(NS"QString", NS"QVariant", d).put(',');
// Std Pairs
putStdPairValueOffsetExpression<int,int>("int","int", d).put(',');
putStdPairValueOffsetExpression<QString,QString>(NS"QString",NS"QString", d).put(',');
putStdPairValueOffsetExpression<int,QString>("int",NS"QString", d).put(',');
putStdPairValueOffsetExpression<QString,int>(NS"QString", "int", d).put(',');
putStdPairValueOffsetExpression<std::string,std::string>(stdStringTypeC, stdStringTypeC, d).put(',');
putStdPairValueOffsetExpression<int,std::string>("int", stdStringTypeC, d).put(',');
putStdPairValueOffsetExpression<std::string,int>(stdStringTypeC, "int", d.put(','));
putStdPairValueOffsetExpression<std::wstring,std::wstring>(stdWideStringTypeUShortC, stdWideStringTypeUShortC, d).put(',');
putStdPairValueOffsetExpression<int,std::wstring>("int", stdWideStringTypeUShortC, d).put(',');
putStdPairValueOffsetExpression<std::wstring,int>(stdWideStringTypeUShortC, "int", d);
d.put('}');
d.disarm();
}
......
......@@ -308,6 +308,18 @@ static int dumpStdStringSet()
return 0;
}
static int dumpStdQStringSet()
{
std::set<QString> test;
test.insert(QLatin1String("item1"));
test.insert(QLatin1String("item2"));
prepareInBuffer("std::set", "local.stringset", "local.stringset", "QString");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
fputc('\n', stdout);
return 0;
}
static int dumpStdMapIntString()
{
std::map<int,std::string> test;
......@@ -322,6 +334,22 @@ static int dumpStdMapIntString()
return 0;
}
static int dumpStdMapStringString()
{
typedef std::map<std::string,std::string> TestType;
TestType test;
const TestType::value_type entry("K", "V");
test.insert(entry);
const int valueOffset = (char*)&(entry.second) - (char*)&entry;
prepareInBuffer("std::map", "local.stdmapstringstring", "local.stdmapstringstring",
"std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::less<int>@std::allocator<std::pair<const std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::string), valueOffset, 0);
fputs(qDumpOutBuffer, stdout);
fputc('\n', stdout);
return 0;
}
static int dumpQObject()
{
// Requires the childOffset to be know, but that is not critical
......@@ -398,7 +426,9 @@ static TypeDumpFunctionMap registerTypes()
rc.insert("vector<wstring>", dumpStdWStringVector);
rc.insert("set<int>", dumpStdIntSet);
rc.insert("set<string>", dumpStdStringSet);
rc.insert("set<QString>", dumpStdQStringSet);
rc.insert("map<int,string>", dumpStdMapIntString);
rc.insert("map<string,string>", dumpStdMapStringString);
rc.insert("QObject", dumpQObject);
rc.insert("QObjectList", dumpQObjectList);
rc.insert("QVariant", dumpQVariant);
......
......@@ -100,7 +100,7 @@ static bool allocDebuggeeMemory(CdbComInterfaces *cif,
OutputRedirector redir(cif->debugClient, &stringHandler);
if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, allocCmd, errorMessage))
return false;
// "Allocated 1000 bytes starting at 003a0000" .. hopefully never localized
// "Allocated 1000 bytes starting at 003a0000" .. hopefully never localized
bool ok = false;
const QString output = stringHandler.result();
const int lastBlank = output.lastIndexOf(QLatin1Char(' '));
......@@ -176,7 +176,7 @@ static bool debuggeeLoadLibrary(IDebuggerManagerAccessForEngines *access,
return false;
// This will hit a breakpoint.
if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, QString(QLatin1Char('g')), errorMessage))
return false;
return false;
const HRESULT hr = cif->debugControl->WaitForEvent(0, waitTimeOutMS);
if (FAILED(hr)) {
*errorMessage = msgComFailed("WaitForEvent", hr);
......@@ -280,7 +280,7 @@ void CdbDumperHelper::moduleLoadHook(const QString &module, HANDLE debuggeeHandl
if (m_tryInjectLoad && module.contains(QLatin1String("Qt"), Qt::CaseInsensitive)) {
// Also shows up in the log window.
m_manager->showStatusMessage(msgLoading(m_library, true), 10000);
QString errorMessage;
QString errorMessage;
SharedLibraryInjector sh(GetProcessId(debuggeeHandle));
if (sh.remoteInject(m_library, false, &errorMessage)) {
m_state = InjectLoading;
......@@ -408,7 +408,7 @@ static inline bool getSymbolAddress(CIDebugSymbols *sg,
}
bool CdbDumperHelper::initResolveSymbols(QString *errorMessage)
{
{
// Resolve the symbols we need (potentially namespaced).
// There is a 'qDumpInBuffer' in QtCore as well.
m_dumpObjectSymbol = QLatin1String("*qDumpObjectData440");
......@@ -437,6 +437,7 @@ bool CdbDumperHelper::initResolveSymbols(QString *errorMessage)
// Call query protocol to retrieve known types and sizes
bool CdbDumperHelper::initKnownTypes(QString *errorMessage)
{
const double dumperVersionRequired = 1.3;
QByteArray output;
QString callCmd;
QTextStream(&callCmd) << ".call " << m_dumpObjectSymbol << "(1,0,0,0,0,0,0,0)";
......@@ -447,6 +448,10 @@ bool CdbDumperHelper::initKnownTypes(QString *errorMessage)
if (!m_helper.parseQuery(outData, QtDumperHelper::CdbDebugger)) {
*errorMessage = QString::fromLatin1("Unable to parse the dumper output: '%1'").arg(QString::fromAscii(output));
}
if (m_helper.dumperVersion() < dumperVersionRequired) {
*errorMessage = QtDumperHelper::msgDumperOutdated(dumperVersionRequired, m_helper.dumperVersion());
return false;
}
if (loadDebug)
qDebug() << Q_FUNC_INFO << m_helper.toString(true);
return true;
......@@ -521,7 +526,7 @@ bool CdbDumperHelper::callDumper(const QString &callCmd, const QByteArray &inBuf
return false;
}
// see QDumper implementation
const char result = m_buffer[0];
const char result = m_buffer[0];
switch (result) {
case 't':
break;
......@@ -574,7 +579,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
}
// Known type?
const QtDumperHelper::TypeData td = m_helper.typeData(wd.type);
const QtDumperHelper::TypeData td = m_helper.typeData(wd.type);
if (loadDebug)
qDebug() << "dumpType" << wd.type << td;
if (td.type == QtDumperHelper::UnknownType) {
......@@ -596,7 +601,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
// yet initialized in a particular breakpoint. That should be ignored.
// Also fail for complex expression that were not cached/replaced by the helper.
if (der == DumpExecuteSizeFailed || der == DumpComplexExpressionEncountered)
m_failedTypes.push_back(wd.type);
m_failedTypes.push_back(wd.type);
// log error
*errorMessage = msgDumpFailed(wd, errorMessage);
m_access->showDebuggerOutput(LogWarning, *errorMessage);
......@@ -609,7 +614,7 @@ CdbDumperHelper::DumpExecuteResult
QList<WatchData> *result, QString *errorMessage)
{
QByteArray inBuffer;
QStringList extraParameters;
QStringList extraParameters;
// Build parameter list.
m_helper.evaluationParameters(wd, td, QtDumperHelper::CdbDebugger, &inBuffer, &extraParameters);
// If the parameter list contains sizeof-expressions, execute them separately
......
......@@ -86,10 +86,12 @@ static inline QString getSymbolString(IDebugSymbolGroup2 *sg,
WideStringRetrievalFunction wsf,
unsigned long index)
{
static WCHAR nameBuffer[MAX_PATH + 1];
// Template type names can get quite long....
enum { BufSize = 1024 };
static WCHAR nameBuffer[BufSize + 1];
// Name
ULONG nameLength;
const HRESULT hr = (sg->*wsf)(index, nameBuffer, MAX_PATH, &nameLength);
const HRESULT hr = (sg->*wsf)(index, nameBuffer, BufSize, &nameLength);
if (SUCCEEDED(hr)) {
nameBuffer[nameLength] = 0;
return QString::fromUtf16(reinterpret_cast<const ushort *>(nameBuffer));
......
......@@ -246,7 +246,7 @@ void GdbEngine::initializeVariables()
m_address.clear();
m_currentFunctionArgs.clear();
m_currentFrame.clear();
m_dumperHelper = QtDumperHelper();
m_dumperHelper.clear();
// FIXME: unhandled:
//m_outputCodecState = QTextCodec::ConverterState();
......@@ -3144,8 +3144,33 @@ void GdbEngine::rebuildModel()
showToolTip();
}
static inline double getDumperVersion(const GdbMi &contents)
{
const GdbMi dumperVersionG = contents.findChild("dumperversion");
if (dumperVersionG.type() != GdbMi::Invalid) {
bool ok;
const double v = QString::fromAscii(dumperVersionG.data()).toDouble(&ok);
if (ok)
return v;
}
return 1.0;
}
static void parseSizeCache(const GdbMi &contents, QtDumperHelper *dumperHelper)
{
const GdbMi sizesList = contents.findChild("sizes");
if (sizesList.type() == GdbMi::Invalid)
return;
foreach(const GdbMi &c, sizesList.children()) {
const QString name = QString::fromAscii(c.name());
if (const int size = QString::fromAscii(c.data()).toInt())
dumperHelper->addSize(name, size);
}
}
void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const QVariant &)
{
const double dumperVersionRequired = 1.0;
m_dumperHelper.clear();
//qDebug() << "DATA DUMPER TRIAL:" << record.toString();
......@@ -3163,7 +3188,6 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
//qDebug() << "FOUND QT VERSION:" << qtversion.toString() << m_qtVersion;
}
m_dumperHelper.setQtVersion(qtv);
//qDebug() << "CONTENTS:" << contents.toString();
//qDebug() << "SIMPLE DUMPERS:" << simple.toString();
......@@ -3176,17 +3200,19 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
m_debuggingHelperState = DebuggingHelperUnavailable;
q->showStatusMessage(tr("Debugging helpers not found."));
//QMessageBox::warning(q->mainWindow(),
// tr("Cannot find special data dumpers"),
// tr("The debugged binary does not contain information needed for "
// "nice display of Qt data types.\n\n"
// "You might want to try including the file\n\n"
// ".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n"
// "into your project directly.")
// );
} else {
// Get version and sizes from dumpers. Expression cache
// currently causes errors.
const double dumperVersion = getDumperVersion(contents);
if (dumperVersion < dumperVersionRequired) {
qq->showQtDumperLibraryWarning(QtDumperHelper::msgDumperOutdated(dumperVersionRequired, dumperVersion));
m_debuggingHelperState = DebuggingHelperUnavailable;
return;
}
parseSizeCache(contents, &m_dumperHelper);
m_debuggingHelperState = DebuggingHelperAvailable;
q->showStatusMessage(tr("%n custom dumpers found.", 0, m_dumperHelper.typeCount()));
const QString successMsg = tr("Dumper version %1, %n custom dumpers found.", 0, m_dumperHelper.typeCount()).arg(dumperVersion);
q->showStatusMessage(successMsg);
}
//qDebug() << m_dumperHelper.toString(true);
//qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE";
......
......@@ -638,20 +638,30 @@ void QtDumperHelper::TypeData::clear()
// ----------------- QtDumperHelper
QtDumperHelper::QtDumperHelper() :
m_qtVersion(0)
m_qtVersion(0),
m_dumperVersion(1.0)
{
qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
setQClassPrefixes(QString());
}
void QtDumperHelper::clear()
{
m_nameTypeMap.clear();
m_qtVersion = 0;
m_dumperVersion = 1.0;
m_qtNamespace.clear();
m_sizeCache.clear();
qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
m_expressionCache.clear();
m_dumperVersion.clear();
setQClassPrefixes(QString());
}
QString QtDumperHelper::msgDumperOutdated(double requiredVersion, double currentVersion)
{
return QCoreApplication::translate("QtDumperHelper",
"Found a too-old version of the debugging helper library (%1); version %2 is required.").
arg(currentVersion).arg(requiredVersion);
}
static inline void formatQtVersion(int v, QTextStream &str)
......@@ -685,7 +695,7 @@ QString QtDumperHelper::toString(bool debug) const
return QCoreApplication::translate("QtDumperHelper",
"%n known types, Qt version: %1, Qt namespace: %2 Dumper version: %3",
0, QCoreApplication::CodecForTr,
m_nameTypeMap.size()).arg(qtVersionString(), nameSpace, m_dumperVersion);
m_nameTypeMap.size()).arg(qtVersionString(), nameSpace).arg(m_dumperVersion);
}
QtDumperHelper::Type QtDumperHelper::simpleType(const QString &simpleType) const
......@@ -774,11 +784,11 @@ QtDumperHelper::ExpressionRequirement QtDumperHelper::expressionRequirements(Typ
switch (t) {
case QAbstractItemType:
case QVectorType:
case StdMapType:
return NeedsComplexExpression;
case QMapType:
case QMultiMapType:
case QMapNodeType:
case StdMapType:
return NeedsCachedExpression;
default:
// QObjectSlotType, QObjectSignalType need the signal number, which is numeric
......@@ -1130,6 +1140,25 @@ bool QueryDumperParser::handleValue(const char *k, int size)
return true;
}
static inline QString qClassName(const QString &qtNamespace, const char *className)
{
if (qtNamespace.isEmpty())
return QString::fromAscii(className);
QString rc = qtNamespace;
rc += QLatin1String("::");
rc += QString::fromAscii(className);
return rc;
}
void QtDumperHelper::setQClassPrefixes(const QString &qNamespace)
{
// Prefixes with namespaces
m_qPointerPrefix = qClassName(qNamespace, "QPointer");
m_qSharedPointerPrefix = qClassName(qNamespace, "QSharedPointer");
m_qSharedDataPointerPrefix = qClassName(qNamespace, "QSharedDataPointer");
m_qWeakPointerPrefix = qClassName(qNamespace, "QWeakPointer");
}
// parse a query
bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
{
......@@ -1139,14 +1168,27 @@ bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
clear();
m_qtNamespace = parser.data().qtNameSpace;
setQtVersion(parser.data().qtVersion);
setQClassPrefixes(m_qtNamespace);
parseQueryTypes(parser.data().types, debugger);
foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes)
addSize(se.first, se.second);
m_expressionCache = parser.data().expressionCache;
m_dumperVersion = parser.data().dumperVersion;
// Version
if (!parser.data().dumperVersion.isEmpty()) {
double dumperVersion;
bool ok;
dumperVersion = parser.data().dumperVersion.toDouble(&ok);
if (ok)
m_dumperVersion = dumperVersion;
}
return true;
}
void QtDumperHelper::addExpression(const QString &expression, const QString &value)
{
m_expressionCache.insert(expression, value);
}
void QtDumperHelper::addSize(const QString &name, int size)
{
// Special interest cases
......@@ -1219,27 +1261,23 @@ QString QtDumperHelper::evaluationSizeofTypeExpression(const QString &typeName,