Commit 36d0d850 authored by con's avatar con
Browse files

Merge commit 'origin/1.3'

parents 040ab7a9 a253a699
......@@ -1095,8 +1095,9 @@
watchers, registers, etc, Qt Creator comes with additional features to make
debugging Qt-based applications easy. The debugger frontend knows about the
internal layout of several Qt classes such as QString, the QTL containers,
and most importantly QObject (and classes derived from it). Therefore, it
is able to present Qt's data clearly.
and most importantly QObject (and classes derived from it), as well as
most containers of the C++ Standard Library, and is therefore able to
present their contents in a useful way.
\section1 Debugger Engine Installation Notes
......@@ -1262,7 +1263,7 @@
parameters of the function in that frame as well as the local variables.
Compound variables of struct or class type will be displayed as
"expandable" in the view. C lick on the "+" to expand the entry and show
"expandable" in the view. Click on the "+" to expand the entry and show
all members. Together with the display of value and type, the user can
examine and traverse the low-level layout of an object's data.
......@@ -1291,8 +1292,8 @@
The \gui{Locals and Watchers} view also provides access to the most
powerful feature of the debugger: comprehensive display of data belonging
to Qt's basic objects. To enable this feature, select \gui{Use Custom
Display for Qt Objects} from the \gui Debug menu.The
to Qt's basic objects. To enable this feature, select \gui{Use
debugging helper} from the \gui Debug menu.The
\gui{Locals and Watchers} view will be re-organized to provide a high-level
view of the objects. For example, in case of QObject, instead of displaying
a pointer to some private data structure, you will see a list of children,
......
......@@ -1613,31 +1613,28 @@ static void qDumpQList(QDumper &d)
// This uses the knowledge that QList<T> has only a single member
// of type union { QListData p; QListData::Data *d; };
const QListData &ldata = *reinterpret_cast<const QListData*>(d.data);
const QListData::Data *pdata =
*reinterpret_cast<const QListData::Data* const*>(d.data);
const int nn = ldata.size();
const QListData &pdata = *reinterpret_cast<const QListData*>(d.data);
const int nn = pdata.size();
if (nn < 0)
return;
const bool innerTypeIsPointer = isPointerType(d.innerType);
const int n = qMin(nn, 1000);
if (nn > 0) {
if (ldata.d->begin < 0)
if (pdata.d->begin < 0)
return;
if (ldata.d->begin > ldata.d->end)
if (pdata.d->begin > pdata.d->end)
return;
#if QT_VERSION >= 0x040400
if (ldata.d->ref._q_value <= 0)
if (pdata.d->ref._q_value <= 0)
return;
#endif
qCheckAccess(ldata.d->array);
qCheckAccess(pdata.d->array);
// Additional checks on pointer arrays
if (innerTypeIsPointer)
for (int i = 0; i != n; ++i)
if (const void *p = ldata.d->array + i + pdata->begin)
if (const void *p = pdata.d->array + i + pdata.d->begin)
qCheckPointer(deref(p));
}
qCheckAccess(pdata);
d.putItemCount("value", nn);
d.putItem("valueeditable", "false");
......@@ -1658,7 +1655,7 @@ static void qDumpQList(QDumper &d)
for (int i = 0; i != n; ++i) {
d.beginHash();
if (innerTypeIsPointer) {
void *p = ldata.d->array + i + pdata->begin;
void *p = pdata.d->array + i + pdata.d->begin;
d.putItem("saddr", p);
if (*(void**)p) {
//d.putItem("value","@").put(p);
......@@ -1668,7 +1665,7 @@ static void qDumpQList(QDumper &d)
d.putItem("numchild", "0");
}
} else {
void *p = ldata.d->array + i + pdata->begin;
void *p = pdata.d->array + i + pdata.d->begin;
if (isInternal) {
//qDumpInnerValue(d, d.innerType, p);
d.putItem("addr", p);
......
......@@ -874,7 +874,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
if (! resolvedTypes.isEmpty()) {
if (m_completionOperator == T_LPAREN &&
completeConstructorOrFunction(resolvedTypes, context, endOfExpression)) {
completeConstructorOrFunction(resolvedTypes, context, endOfExpression, false)) {
return m_startPosition;
} else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) &&
......@@ -913,7 +913,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
// If it's a class, add completions for the constructors
foreach (const TypeOfExpression::Result &result, results) {
if (result.first->isClassType()) {
if (completeConstructorOrFunction(results, context, endOfExpression))
if (completeConstructorOrFunction(results, context, endOfExpression, true))
return m_startPosition;
break;
}
......@@ -927,7 +927,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpression::Result> &results,
const LookupContext &context,
int endOfExpression)
int endOfExpression, bool toolTipOnly)
{
QList<Function *> functions;
......@@ -1016,15 +1016,17 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
}
}
if (! functions.isEmpty()) {
// There are two options:
// 1. If this is a function call, we want to pop up a tooltip that shows the user
// the possible overloads with their argument types and names.
// 2. If this is a function definition, we want to offer autocompletion of
// the function signature.
// There are two different kinds of completion we want to provide:
// 1. If this is a function call, we want to pop up a tooltip that shows the user
// the possible overloads with their argument types and names.
// 2. If this is a function definition, we want to offer autocompletion of
// the function signature.
// Here we evaluate a first criterion: function definitions will only
// happen in class or namespace scope.
// check if function signature autocompletion is appropriate
if (! functions.isEmpty() && ! toolTipOnly) {
// function definitions will only happen in class or namespace scope,
// so get the current location's enclosing scope.
// get current line and column
TextEditor::BaseTextEditor *edit = qobject_cast<TextEditor::BaseTextEditor *>(m_editor->widget());
......@@ -1046,16 +1048,16 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
unsigned endLine, endColumn;
context.thisDocument()->translationUnit()->getPosition(sc->owner()->endOffset(), &endLine, &endColumn);
if (startLine <= line && line <= endLine)
if (startLine <= line && line <= endLine) {
if ((startLine != line || startColumn <= column)
&& (endLine != line || column <= endColumn))
break;
}
sc = sc->enclosingScope();
}
if (sc && (sc->isClassScope() || sc->isNamespaceScope()))
{
if (sc && (sc->isClassScope() || sc->isNamespaceScope())) {
// It may still be a function call. If the whole line parses as a function
// declaration, we should be certain that it isn't.
bool autocompleteSignature = false;
......@@ -1094,7 +1096,9 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
return true;
}
}
}
if (! functions.empty()) {
// set up function call tooltip
// Recreate if necessary
......
......@@ -118,7 +118,7 @@ private:
bool completeConstructorOrFunction(const QList<CPlusPlus::TypeOfExpression::Result> &,
const CPlusPlus::LookupContext &,
int endOfExpression);
int endOfExpression, bool toolTipOnly);
bool completeMember(const QList<CPlusPlus::TypeOfExpression::Result> &,
const CPlusPlus::LookupContext &context);
......
......@@ -1270,6 +1270,11 @@ void GdbEngine::handleStop1(const GdbMi &data)
if (m_sourcesListOutdated)
reloadSourceFilesInternal(); // This needs to be done before fullName() may need it
// Older gdb versions do not produce "library loaded" messages
// so the breakpoint update is not triggered.
if (m_gdbVersion < 70000 && !m_isMacGdb)
postCommand(_("-break-list"), CB(handleBreakList));
QByteArray reason = data.findChild("reason").data();
if (reason == "breakpoint-hit") {
showStatusMessage(tr("Stopped at breakpoint."));
......
......@@ -363,19 +363,25 @@ bool startCreatorAsDebugger(QString *errorMessage)
return true;
}
bool startDefaultDebugger(QString *errorMessage)
bool readDefaultDebugger(QString *defaultDebugger,
QString *errorMessage)
{
// Read out default value
bool success = false;
HKEY handle;
if (!openRegistryKey(HKEY_LOCAL_MACHINE, optIsWow ? debuggerWow32RegistryKeyC : debuggerRegistryKeyC,
false, &handle, errorMessage))
return false;
QString defaultDebugger;
if (!registryReadStringKey(handle, debuggerRegistryDefaultValueNameC, &defaultDebugger, errorMessage)) {
if (openRegistryKey(HKEY_LOCAL_MACHINE, optIsWow ? debuggerWow32RegistryKeyC : debuggerRegistryKeyC,
false, &handle, errorMessage)) {
success = registryReadStringKey(handle, debuggerRegistryDefaultValueNameC,
defaultDebugger, errorMessage);
RegCloseKey(handle);
return false;
}
RegCloseKey(handle);
return success;
}
bool startDefaultDebugger(QString *errorMessage)
{
QString defaultDebugger;
if (!readDefaultDebugger(&defaultDebugger, errorMessage))
return false;
// binary, replace placeholders by pid/event id
if (debug)
qDebug() << "Default" << defaultDebugger;
......@@ -401,10 +407,13 @@ bool startDefaultDebugger(QString *errorMessage)
bool chooseDebugger(QString *errorMessage)
{
QString defaultDebugger;
const QString msg = QString::fromLatin1("The application \"%1\" (process id %2) crashed. Would you like to debug it?").arg(getProcessBaseName(argProcessId)).arg(argProcessId);
QMessageBox msgBox(QMessageBox::Information, QLatin1String(titleC), msg, QMessageBox::Cancel);
QPushButton *creatorButton = msgBox.addButton(QLatin1String("Debug with Qt Creator"), QMessageBox::AcceptRole);
QPushButton *defaultButton = msgBox.addButton(QLatin1String("Debug with default debugger"), QMessageBox::AcceptRole);
defaultButton->setEnabled(readDefaultDebugger(&defaultDebugger, errorMessage)
&& !defaultDebugger.isEmpty());
msgBox.exec();
if (msgBox.clickedButton() == creatorButton) {
// Just in case, default to standard
......@@ -444,12 +453,12 @@ static bool registerDebuggerKey(const WCHAR *key,
do {
if (!openRegistryKey(HKEY_LOCAL_MACHINE, key, true, &handle, errorMessage))
break;
// Save old key, which might be missing
QString oldDebugger;
if (!registryReadStringKey(handle, debuggerRegistryValueNameC, &oldDebugger, errorMessage))
break;
registryReadStringKey(handle, debuggerRegistryValueNameC, &oldDebugger, errorMessage);
if (oldDebugger.contains(QLatin1String(applicationFileC), Qt::CaseInsensitive)) {
*errorMessage = QLatin1String("The program is already registered as post mortem debugger.");
return false;
break;
}
if (!registryWriteStringKey(handle, debuggerRegistryDefaultValueNameC, oldDebugger, errorMessage))
break;
......@@ -483,11 +492,24 @@ static bool unregisterDebuggerKey(const WCHAR *key, QString *errorMessage)
do {
if (!openRegistryKey(HKEY_LOCAL_MACHINE, key, true, &handle, errorMessage))
break;
QString debugger;
registryReadStringKey(handle, debuggerRegistryValueNameC, &debugger, errorMessage);
if (!(debugger.isEmpty()
|| debugger.contains(QLatin1String(applicationFileC), Qt::CaseInsensitive))) {
*errorMessage = QLatin1String("The program is not registered as post mortem debugger.");
break;
}
QString oldDebugger;
if (!registryReadStringKey(handle, debuggerRegistryDefaultValueNameC, &oldDebugger, errorMessage))
break;
if (!registryWriteStringKey(handle, debuggerRegistryValueNameC, oldDebugger, errorMessage))
break;
// Re-register old debugger or delete key if it was empty.
if (oldDebugger.isEmpty()) {
if (!registryDeleteValue(handle, debuggerRegistryValueNameC, errorMessage))
break;
} else {
if (!registryWriteStringKey(handle, debuggerRegistryValueNameC, oldDebugger, errorMessage))
break;
}
if (!registryDeleteValue(handle, debuggerRegistryDefaultValueNameC, errorMessage))
break;
success = true;
......
......@@ -145,6 +145,7 @@ private slots:
void dumpQImageData();
void dumpQLinkedList();
void dumpQList_int();
void dumpQList_int_star();
void dumpQList_char();
void dumpQList_QString();
void dumpQList_QString3();
......@@ -1392,6 +1393,22 @@ void tst_Debugger::dumpQList_int()
&ilist, NS"QList", true, "int");
}
void tst_Debugger::dumpQList_int_star()
{
QList<int *> ilist;
testDumper("value='<0 items>',valueeditable='false',numchild='0',"
"internal='1',children=[]",
&ilist, NS"QList", true, "int*");
ilist.append(new int(1));
ilist.append(0);
testDumper("value='<2 items>',valueeditable='false',numchild='2',"
"internal='1',childtype='int*',childnumchild='1',children=["
"{saddr='" + str(&ilist.at(0)) + "',addr='" + str(deref(&ilist.at(0))) +
"',type='int',value='1'},"
"{saddr='" + str(&ilist.at(1)) + "',value='<null>',numchild='0'}]",
&ilist, NS"QList", true, "int*");
}
void tst_Debugger::dumpQList_char()
{
QList<char> clist;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment