From 8aa8f225369603e1e9ea019ca043715b08a61e82 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 11 Jun 2013 09:22:18 +0200 Subject: [PATCH 1/6] C++: Handle recursive auto declarations Remember auto declarations we have already looked up and stop if we try it again. Task-number: QTCREATORBUG-9503 Change-Id: I989b11609c98bf197ce916d79c9d452294355053 Reviewed-by: Przemyslaw Gorszkowski Reviewed-by: Erik Verbruggen (cherry picked from commit 8f1b6656677344e9ca4b6798ddd900725c478b16) --- src/libs/cplusplus/ResolveExpression.cpp | 15 ++++-- src/libs/cplusplus/ResolveExpression.h | 5 +- src/libs/cplusplus/TypeOfExpression.cpp | 8 ++-- src/libs/cplusplus/TypeOfExpression.h | 9 +++- src/plugins/cpptools/cppcompletion_test.cpp | 53 +++++++++++++++++++++ src/plugins/cpptools/cpptoolsplugin.h | 2 + 6 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index b547c22d68f..32dcbeb4e60 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -75,11 +75,13 @@ static QList<_Tp> removeDuplicates(const QList<_Tp> &results) ///////////////////////////////////////////////////////////////////// // ResolveExpression ///////////////////////////////////////////////////////////////////// -ResolveExpression::ResolveExpression(const LookupContext &context) +ResolveExpression::ResolveExpression(const LookupContext &context, + const QSet &autoDeclarationsBeingResolved) : ASTVisitor(context.expressionDocument()->translationUnit()), _scope(0), _context(context), bind(context.expressionDocument()->translationUnit()), + _autoDeclarationsBeingResolved(autoDeclarationsBeingResolved), _reference(false) { } @@ -519,6 +521,10 @@ bool ResolveExpression::visit(SimpleNameAST *ast) if (!decl) continue; + // Stop on recursive auto declarations + if (_autoDeclarationsBeingResolved.contains(decl)) + continue; + const StringLiteral *initializationString = decl->getInitializer(); if (initializationString == 0) continue; @@ -533,7 +539,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast) TypeOfExpression exprTyper; Document::Ptr doc = _context.snapshot().document(QString::fromLocal8Bit(decl->fileName())); - exprTyper.init(doc, _context.snapshot(), _context.bindings()); + exprTyper.init(doc, _context.snapshot(), _context.bindings(), + QSet(_autoDeclarationsBeingResolved) << decl); Document::Ptr exprDoc = documentForExpression(exprTyper.preprocessedExpression(initializer)); @@ -543,8 +550,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast) if (deduceAuto._block) continue; - const QList &typeItems = - exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope()); + const QList &typeItems = exprTyper(extractExpressionAST(exprDoc), exprDoc, + decl->enclosingScope()); if (typeItems.empty()) continue; diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index e6ce50dde49..922d1b6bf0f 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -42,7 +42,9 @@ namespace CPlusPlus { class CPLUSPLUS_EXPORT ResolveExpression: protected ASTVisitor { public: - ResolveExpression(const LookupContext &context); + ResolveExpression(const LookupContext &context, + const QSet &autoDeclarationsBeingResolved + = QSet()); virtual ~ResolveExpression(); QList operator()(ExpressionAST *ast, Scope *scope); @@ -125,6 +127,7 @@ private: const LookupContext& _context; Bind bind; QList _results; + QSet _autoDeclarationsBeingResolved; bool _reference; }; diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index ac813fa873f..7025c474c13 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -58,7 +58,8 @@ void TypeOfExpression::reset() } void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot, - QSharedPointer bindings) + QSharedPointer bindings, + const QSet &autoDeclarationsBeingResolved) { m_thisDocument = thisDocument; m_snapshot = snapshot; @@ -67,6 +68,7 @@ void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot m_lookupContext = LookupContext(); m_bindings = bindings; m_environment.clear(); + m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved; } QList TypeOfExpression::operator()(const QByteArray &utf8code, @@ -111,7 +113,7 @@ QList TypeOfExpression::operator()(ExpressionAST *expression, m_lookupContext.setBindings(m_bindings); m_lookupContext.setExpandTemplates(m_expandTemplates); - ResolveExpression resolve(m_lookupContext); + ResolveExpression resolve(m_lookupContext, m_autoDeclarationsBeingResolved); const QList items = resolve(m_ast, scope); if (! m_bindings) @@ -133,7 +135,7 @@ QList TypeOfExpression::reference(ExpressionAST *expression, m_lookupContext.setBindings(m_bindings); m_lookupContext.setExpandTemplates(m_expandTemplates); - ResolveExpression resolve(m_lookupContext); + ResolveExpression resolve(m_lookupContext, m_autoDeclarationsBeingResolved); const QList items = resolve.reference(m_ast, scope); if (! m_bindings) diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h index adeb1d9644e..a6743e39891 100644 --- a/src/libs/cplusplus/TypeOfExpression.h +++ b/src/libs/cplusplus/TypeOfExpression.h @@ -58,8 +58,11 @@ public: * Also clears the lookup context, so can be used to make sure references * to the documents previously used are removed. */ - void init(Document::Ptr thisDocument, const Snapshot &snapshot, - QSharedPointer bindings = QSharedPointer()); + void init(Document::Ptr thisDocument, + const Snapshot &snapshot, + QSharedPointer bindings = QSharedPointer(), + const QSet &autoDeclarationsBeingResolved + = QSet()); void reset(); @@ -151,6 +154,8 @@ private: // Keep the expression documents and thus all the symbols and // their types alive until they are not needed any more. QList m_documents; + + QSet m_autoDeclarationsBeingResolved; }; ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc); diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 11e380092b2..44f9178cdb8 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -1832,3 +1832,56 @@ void CppToolsPlugin::test_completion_crash_cloning_template_class_QTCREATORBUG93 QVERIFY(completions.contains(QLatin1String("Templ"))); QVERIFY(completions.contains(QLatin1String("f"))); } + +void CppToolsPlugin::test_completion_recursive_auto_declarations1_QTCREATORBUG9503() +{ + TestData data; + data.srcText = + "void f()\n" + "{\n" + " auto object2 = object1;\n" + " auto object1 = object2;\n" + " @;\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("object1."); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 0); +} + +void CppToolsPlugin::test_completion_recursive_auto_declarations2_QTCREATORBUG9503() +{ + TestData data; + data.srcText = + "void f()\n" + "{\n" + " auto object3 = object1;\n" + " auto object2 = object3;\n" + " auto object1 = object2;\n" + " @;\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("object1."); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 0); +} diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index bf9c9b67a5b..0b3998c9e6e 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -128,6 +128,8 @@ private slots: void test_completion_typedef_using_templates2(); void test_completion_namespace_alias_with_many_namespace_declarations(); void test_completion_crash_cloning_template_class_QTCREATORBUG9329(); + void test_completion_recursive_auto_declarations1_QTCREATORBUG9503(); + void test_completion_recursive_auto_declarations2_QTCREATORBUG9503(); void test_format_pointerdeclaration_in_simpledeclarations(); void test_format_pointerdeclaration_in_simpledeclarations_data(); From a3cb35edbebf35b0bc1a89c9e274b6c5c7b428a8 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 11 Jun 2013 10:22:10 +0200 Subject: [PATCH 2/6] C++: Handle recursive using/typedef declarations Remember using/typedef declarations we have already looked up and stop if we try it again. Change-Id: I91bf0aef4df18539a47d015f0113543aef1f692a Reviewed-by: Erik Verbruggen (cherry picked from commit 50a900e509be2e1f448f29be126ba3b7f8173901) --- src/libs/cplusplus/LookupContext.cpp | 13 +- src/libs/cplusplus/LookupContext.h | 4 +- src/plugins/cpptools/cppcompletion_test.cpp | 137 ++++++++++++++++++++ src/plugins/cpptools/cpptoolsplugin.h | 5 + 4 files changed, 155 insertions(+), 4 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index a8a65fd7b84..aa292ee1943 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -275,7 +275,8 @@ ClassOrNamespace *LookupContext::globalNamespace() const } ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope, - ClassOrNamespace* enclosingTemplateInstantiation) const + ClassOrNamespace* enclosingTemplateInstantiation, + QSet typedefsBeingResolved) const { if (! scope) { return 0; @@ -294,8 +295,14 @@ ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope, Overview oo; qDebug() << "Looks like" << oo(name) << "is a typedef for" << oo(d->type()); #endif // DEBUG_LOOKUP - if (const NamedType *namedTy = d->type()->asNamedType()) - return lookupType(namedTy->name(), scope); + if (const NamedType *namedTy = d->type()->asNamedType()) { + // Stop on recursive typedef declarations + if (typedefsBeingResolved.contains(d)) + return 0; + return lookupType(namedTy->name(), scope, 0, + QSet(typedefsBeingResolved) + << d); + } } } } diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index 98ff7ffdbe5..eb4349b7417 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -282,7 +282,9 @@ public: QList lookup(const Name *name, Scope *scope) const; ClassOrNamespace *lookupType(const Name *name, Scope *scope, - ClassOrNamespace* enclosingTemplateInstantiation = 0) const; + ClassOrNamespace* enclosingTemplateInstantiation = 0, + QSet typedefsBeingResolved + = QSet()) const; ClassOrNamespace *lookupType(Symbol *symbol, ClassOrNamespace* enclosingTemplateInstantiation = 0) const; ClassOrNamespace *lookupParent(Symbol *symbol) const; diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 44f9178cdb8..0be0fa1b53c 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -1885,3 +1885,140 @@ void CppToolsPlugin::test_completion_recursive_auto_declarations2_QTCREATORBUG95 QCOMPARE(completions.size(), 0); } + +void CppToolsPlugin::test_completion_recursive_typedefs_declarations1() +{ + TestData data; + data.srcText = + "void f()\n" + "{\n" + " typedef A B;\n" + " typedef B A;\n" + " A a;\n" + " @;\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("a."); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 0); +} + +void CppToolsPlugin::test_completion_recursive_typedefs_declarations2() +{ + TestData data; + data.srcText = + "void f()\n" + "{\n" + " typedef A C;\n" + " typedef C B;\n" + " typedef B A;\n" + " A a;\n" + " @;\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("a."); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 0); +} + +void CppToolsPlugin::test_completion_recursive_using_declarations1() +{ + TestData data; + data.srcText = + "void f()\n" + "{\n" + " using B = A;\n" + " using A = B;\n" + " A a;\n" + " @;\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("a."); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 0); +} + +void CppToolsPlugin::test_completion_recursive_using_declarations2() +{ + TestData data; + data.srcText = + "void f()\n" + "{\n" + " using C = A;\n" + " using B = C;\n" + " using A = B;\n" + " A a;\n" + " @;\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("a."); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 0); +} + +void CppToolsPlugin::test_completion_recursive_using_typedef_declarations() +{ + TestData data; + data.srcText = + "void f()\n" + "{\n" + " using B = A;\n" + " typedef B A;\n" + " A a;\n" + " @;\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("a."); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 0); +} diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index 0b3998c9e6e..3d264f16538 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -130,6 +130,11 @@ private slots: void test_completion_crash_cloning_template_class_QTCREATORBUG9329(); void test_completion_recursive_auto_declarations1_QTCREATORBUG9503(); void test_completion_recursive_auto_declarations2_QTCREATORBUG9503(); + void test_completion_recursive_typedefs_declarations1(); + void test_completion_recursive_typedefs_declarations2(); + void test_completion_recursive_using_declarations1(); + void test_completion_recursive_using_declarations2(); + void test_completion_recursive_using_typedef_declarations(); void test_format_pointerdeclaration_in_simpledeclarations(); void test_format_pointerdeclaration_in_simpledeclarations_data(); From bd5583eb9d14776edab426457939112f38580cd9 Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Mon, 24 Jun 2013 16:41:28 +0200 Subject: [PATCH 3/6] process_stub_unix: fix race condition with reading of env file The stub incorrectly send its pid before reading the environment file, and qtcreator does interpret that as sign that it can delete the environment file. Task-number: QTCREATORBUG-9024 Change-Id: Id44777abdfdd94aa10815cb00ca27846b95a3ec7 Reviewed-by: Oswald Buddenhagen --- src/libs/utils/process_stub_unix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/utils/process_stub_unix.c b/src/libs/utils/process_stub_unix.c index 7ab6a3e0bf0..c561ce902c2 100644 --- a/src/libs/utils/process_stub_unix.c +++ b/src/libs/utils/process_stub_unix.c @@ -198,8 +198,6 @@ int main(int argc, char *argv[]) isDebug = !strcmp(argv[ArgAction], "debug"); isDetached = 0; - sendMsg("spid %ld\n", (long)getpid()); - if (*argv[ArgDir] && chdir(argv[ArgDir])) { /* Only expected error: no such file or direcotry */ sendMsg("err:chdir %d\n", errno); @@ -235,6 +233,8 @@ int main(int argc, char *argv[]) env[count] = 0; } + /* send our pid after we read the environment file (creator will get rid of it) */ + sendMsg("spid %ld\n", (long)getpid()); /* * set up the signal handlers From ded99d1e091d4b1f6ab66fdee96e9e8ced8eb6c0 Mon Sep 17 00:00:00 2001 From: El Mehdi Fekari Date: Tue, 25 Jun 2013 13:56:32 +0200 Subject: [PATCH 4/6] Qnx: Fix tag for splashscreens Task-number: QTCREATORBUG-9626 Task-number: QTCREATORBUG-9083 Cherry-picked: 4ff03aa71a7122d4573d4dc270a0847818842054 Change-Id: I69915d9da91cde39b1bc32f150c30a5e97cba157 Reviewed-by: Eike Ziller --- src/plugins/qnx/bardescriptordocumentnodehandlers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qnx/bardescriptordocumentnodehandlers.cpp b/src/plugins/qnx/bardescriptordocumentnodehandlers.cpp index a547fbf16db..0eafe048b1f 100644 --- a/src/plugins/qnx/bardescriptordocumentnodehandlers.cpp +++ b/src/plugins/qnx/bardescriptordocumentnodehandlers.cpp @@ -349,7 +349,7 @@ QDomNode BarDescriptorDocumentSplashScreenNodeHandler::toNode(QDomDocument &doc) if (splashScreens.isEmpty()) return QDomElement(); - QDomElement splashScreenElement = doc.createElement(QLatin1String("splashscreens")); + QDomElement splashScreenElement = doc.createElement(QLatin1String("splashScreens")); foreach (const QString &splashScreen, splashScreens) splashScreenElement.appendChild(createSimpleTextElement(doc, QLatin1String("image"), splashScreen)); From e02788b8cef93bd78ae1ce4bca6f242f9e9bfe38 Mon Sep 17 00:00:00 2001 From: El Mehdi Fekari Date: Mon, 24 Jun 2013 11:35:21 +0200 Subject: [PATCH 5/6] Qnx: add a dependency to the debugger plugin This is already done in Master and 2.8 branches. Task-number: QTCREATORBUG-9455 Change-Id: I8ae9e5a14ba561640d3389e08cb74a5ec856d335 Reviewed-by: Eike Ziller --- src/plugins/plugins.pro | 1 + src/plugins/qnx/Qnx.pluginspec.in | 1 + src/plugins/qnx/qnx_dependencies.pri | 1 + 3 files changed, 3 insertions(+) diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 8f34a8a3d54..47f0ed5846e 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -340,6 +340,7 @@ plugin_qnx.depends = plugin_remotelinux plugin_qnx.depends += plugin_qt4projectmanager plugin_qnx.depends += plugin_coreplugin plugin_qnx.depends += plugin_texteditor +plugin_qnx.depends += plugin_debugger plugin_qbsprojectmanager.subdir = qbsprojectmanager plugin_qbsprojectmanager.depends = plugin_texteditor diff --git a/src/plugins/qnx/Qnx.pluginspec.in b/src/plugins/qnx/Qnx.pluginspec.in index aef4606b33d..096a8e7d06a 100644 --- a/src/plugins/qnx/Qnx.pluginspec.in +++ b/src/plugins/qnx/Qnx.pluginspec.in @@ -17,5 +17,6 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General + diff --git a/src/plugins/qnx/qnx_dependencies.pri b/src/plugins/qnx/qnx_dependencies.pri index 7ad421acfa8..9ac66e0a9bd 100644 --- a/src/plugins/qnx/qnx_dependencies.pri +++ b/src/plugins/qnx/qnx_dependencies.pri @@ -2,3 +2,4 @@ include(../../plugins/coreplugin/coreplugin.pri) include(../../plugins/qt4projectmanager/qt4projectmanager.pri) include(../../plugins/remotelinux/remotelinux.pri) include(../../plugins/texteditor/texteditor.pri) +include(../../plugins/debugger/debugger.pri) From c219a5b5142752fab50fe761e815959cc16fabe1 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 25 Jun 2013 17:13:51 +0200 Subject: [PATCH 6/6] QmlProfiler: Avoid idle engine cancelling other engine's process Task-number: QTCREATORBUG-9643 Change-Id: Ia0a2427a186fd9ad24e1cf620df48be13032a69b Reviewed-by: Christian Stenger Reviewed-by: Kai Koehne --- src/plugins/qmlprofiler/qmlprofilerengine.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.cpp b/src/plugins/qmlprofiler/qmlprofilerengine.cpp index 6914286dc66..8523e3d95e1 100644 --- a/src/plugins/qmlprofiler/qmlprofilerengine.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -249,6 +249,10 @@ void QmlProfilerEngine::cancelProcess() { QTC_ASSERT(d->m_profilerState, return); + // no process to be canceled? (there might be multiple engines, but only one runs a process) + if (!d->m_runner) + return; + switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppReadyToStop : { d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped);