aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2017-04-23 17:36:41 +0200
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-04-27 15:16:00 +0200
commitc9728926a878a0e2301ee9d2bfb0ab23862d810b (patch)
tree4124d54365035011a7b46f80b45282a33099be7f
parent93bc4113f06dce4c942374d765bef20054cd1f94 (diff)
parent8d0d1b11e381130dec12f46b959c3107c3f47160 (diff)
Merge remote-tracking branch 'origin/5.8' into 5.9
Conflicts: src/qtqmlglobal.h src/qtqmlglobal_p.h src/jsruntime/qv4global_p.h src/qml/compiler/compiler.pri src/qml/compiler/qv4ssa.cpp src/qmldevtools/qtqmldevtoolsglobal_p.h tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp Change-Id: I55c5d015b2cb1053b83b9c61caaf004fb49ee486
-rw-r--r--src/qml/compiler/compiler.pri3
-rw-r--r--src/qml/compiler/qv4jsir.cpp4
-rw-r--r--src/qml/compiler/qv4jsir_p.h1
-rw-r--r--src/qml/compiler/qv4ssa.cpp336
-rw-r--r--src/qml/jsruntime/qv4global_p.h10
-rw-r--r--src/qml/qtqmlglobal.h6
-rw-r--r--src/qml/qtqmlglobal_p.h8
-rw-r--r--src/qmldevtools/qmldevtools.pro6
-rw-r--r--src/qmldevtools/qtqmldevtoolsglobal_p.h73
-rw-r--r--sync.profile6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qtbug_59012.qml14
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp9
12 files changed, 220 insertions, 256 deletions
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index 871f28f2d0..31ee917b39 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -41,7 +41,7 @@ SOURCES += \
unix: SOURCES += $$PWD/qv4compilationunitmapper_unix.cpp
else: SOURCES += $$PWD/qv4compilationunitmapper_win.cpp
-qtConfig(private_tests): LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD
+qtConfig(private_tests):unix: QMAKE_USE_PRIVATE += libdl
}
qmldevtools_build|qtConfig(qml-interpreter) {
@@ -52,4 +52,3 @@ qmldevtools_build|qtConfig(qml-interpreter) {
$$PWD/qv4instr_moth.cpp \
$$PWD/qv4isel_moth.cpp
}
-
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index cc2f9b7cf2..5a58380005 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -444,10 +444,6 @@ void Function::setScheduledBlocks(const QVector<BasicBlock *> &scheduled)
Q_ASSERT(!_allBasicBlocks);
_allBasicBlocks = new QVector<BasicBlock *>(basicBlocks());
_basicBlocks = scheduled;
-}
-
-void Function::renumberBasicBlocks()
-{
for (int i = 0, ei = basicBlockCount(); i != ei; ++i)
basicBlock(i)->changeIndex(i);
}
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index e3c20a4cc8..caab9c0f9e 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -1348,7 +1348,6 @@ struct Function {
{ return hasDirectEval || !nestedFunctions.isEmpty() || module->debugMode; }
void setScheduledBlocks(const QVector<BasicBlock *> &scheduled);
- void renumberBasicBlocks();
int getNewStatementId() { return _statementCount++; }
int statementCount() const { return _statementCount; }
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 62e2833089..731c6ad38f 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -3025,14 +3025,19 @@ void splitCriticalEdges(IR::Function *f, DominatorTree &df, StatementWorklist &w
// add newBB to the correct loop group
if (toBB->isGroupStart()) {
- BasicBlock *container;
- for (container = fromBB->containingGroup(); container; container = container->containingGroup())
- if (container == toBB)
- break;
- if (container == toBB) // if we were already inside the toBB loop
+ if (fromBB == toBB) {
+ // special case: the loop header points back to itself (so it's a small loop).
newBB->setContainingGroup(toBB);
- else
- newBB->setContainingGroup(toBB->containingGroup());
+ } else {
+ BasicBlock *container;
+ for (container = fromBB->containingGroup(); container; container = container->containingGroup())
+ if (container == toBB)
+ break;
+ if (container == toBB) // if we were already inside the toBB loop
+ newBB->setContainingGroup(toBB);
+ else
+ newBB->setContainingGroup(toBB->containingGroup());
+ }
} else {
newBB->setContainingGroup(toBB->containingGroup());
}
@@ -3063,7 +3068,7 @@ void splitCriticalEdges(IR::Function *f, DominatorTree &df, StatementWorklist &w
bool toNeedsNewIdom = true;
for (BasicBlock *bb : toBB->in) {
- if (bb != newBB && !df.dominates(toBB, bb)) {
+ if (bb != newBB && bb != toBB && !df.dominates(toBB, bb)) {
toNeedsNewIdom = false;
break;
}
@@ -3174,7 +3179,7 @@ public:
backedges.clear();
for (BasicBlock *in : bb->in)
- if (dt.dominates(bb, in))
+ if (bb == in || dt.dominates(bb, in))
backedges.push_back(in);
if (!backedges.empty()) {
@@ -3191,6 +3196,7 @@ public:
if (!DebugLoopDetection)
return;
+ qDebug() << "Found" << loopInfos.size() << "loops";
for (const LoopInfo *info : loopInfos) {
qDebug() << "Loop header:" << info->loopHeader->index()
<< "for loop" << quint64(info);
@@ -3224,6 +3230,9 @@ private:
void subLoop(BasicBlock *loopHead, const std::vector<BasicBlock *> &backedges)
{
loopHead->markAsGroupStart();
+ LoopInfo *info = new LoopInfo;
+ info->loopHeader = loopHead;
+ loopInfos.append(info);
std::vector<BasicBlock *> worklist;
worklist.reserve(backedges.size() + 8);
@@ -3293,10 +3302,8 @@ private:
return info;
}
- LoopInfo *info = new LoopInfo;
- info->loopHeader = loopHeader;
- loopInfos.append(info);
- return info;
+ Q_UNREACHABLE();
+ return nullptr;
}
};
@@ -3326,6 +3333,8 @@ private:
// the same reason.
class BlockScheduler
{
+ enum { DebugBlockScheduler = 0 };
+
IR::Function *function;
const DominatorTree &dominatorTree;
@@ -3441,6 +3450,14 @@ class BlockScheduler
Q_UNREACHABLE();
}
+ void dumpLoopStartsEnds() const
+ {
+ qDebug() << "Found" << loopsStartEnd.size() << "loops:";
+ for (auto key : loopsStartEnd.keys())
+ qDebug("Loop starting at L%d ends at L%d.", key->index(),
+ loopsStartEnd.value(key)->index());
+ }
+
public:
BlockScheduler(IR::Function *function, const DominatorTree &dominatorTree)
: function(function)
@@ -3452,11 +3469,15 @@ public:
QHash<BasicBlock *, BasicBlock *> go()
{
showMeTheCode(function, "Before block scheduling");
+ if (DebugBlockScheduler)
+ dominatorTree.dumpImmediateDominators();
+
schedule(function->basicBlock(0));
Q_ASSERT(function->liveBasicBlocksCount() == sequence.size());
function->setScheduledBlocks(sequence);
- function->renumberBasicBlocks();
+ if (DebugBlockScheduler)
+ dumpLoopStartsEnds();
return loopsStartEnd;
}
};
@@ -4592,7 +4613,6 @@ void removeUnreachleBlocks(IR::Function *function)
if (!bb->isRemoved())
newSchedule.append(bb);
function->setScheduledBlocks(newSchedule);
- function->renumberBasicBlocks();
}
class ConvertArgLocals
@@ -4766,6 +4786,137 @@ private:
IR::Stmt *clonedStmt;
};
+static void verifyCFG(IR::Function *function)
+{
+ if (!DoVerification)
+ return;
+
+ for (BasicBlock *bb : function->basicBlocks()) {
+ if (bb->isRemoved()) {
+ Q_ASSERT(bb->in.isEmpty());
+ Q_ASSERT(bb->out.isEmpty());
+ continue;
+ }
+
+ Q_ASSERT(function->basicBlock(bb->index()) == bb);
+
+ // Check the terminators:
+ Stmt *terminator = bb->terminator();
+ if (terminator == nullptr) {
+ Stmt *last = bb->statements().last();
+ Call *call = last->asExp()->expr->asCall();
+ Name *baseName = call->base->asName();
+ Q_ASSERT(baseName->builtin == Name::builtin_rethrow);
+ Q_UNUSED(baseName);
+ } else if (Jump *jump = terminator->asJump()) {
+ Q_UNUSED(jump);
+ Q_ASSERT(jump->target);
+ Q_ASSERT(!jump->target->isRemoved());
+ Q_ASSERT(bb->out.size() == 1);
+ Q_ASSERT(bb->out.first() == jump->target);
+ } else if (CJump *cjump = terminator->asCJump()) {
+ Q_UNUSED(cjump);
+ Q_ASSERT(bb->out.size() == 2);
+ Q_ASSERT(cjump->iftrue);
+ Q_ASSERT(!cjump->iftrue->isRemoved());
+ Q_ASSERT(cjump->iftrue == bb->out[0]);
+ Q_ASSERT(cjump->iffalse);
+ Q_ASSERT(!cjump->iffalse->isRemoved());
+ Q_ASSERT(cjump->iffalse == bb->out[1]);
+ } else if (terminator->asRet()) {
+ Q_ASSERT(bb->out.size() == 0);
+ } else {
+ Q_UNREACHABLE();
+ }
+
+ // Check the outgoing edges:
+ for (BasicBlock *out : bb->out) {
+ Q_UNUSED(out);
+ Q_ASSERT(!out->isRemoved());
+ Q_ASSERT(out->in.contains(bb));
+ }
+
+ // Check the incoming edges:
+ for (BasicBlock *in : bb->in) {
+ Q_UNUSED(in);
+ Q_ASSERT(!in->isRemoved());
+ Q_ASSERT(in->out.contains(bb));
+ }
+ }
+}
+
+static void verifyImmediateDominators(const DominatorTree &dt, IR::Function *function)
+{
+ if (!DoVerification)
+ return;
+
+ cfg2dot(function);
+ dt.dumpImmediateDominators();
+ DominatorTree referenceTree(function);
+
+ for (BasicBlock *bb : function->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+
+ BasicBlock *idom = dt.immediateDominator(bb);
+ BasicBlock *referenceIdom = referenceTree.immediateDominator(bb);
+ Q_UNUSED(idom);
+ Q_UNUSED(referenceIdom);
+ Q_ASSERT(idom == referenceIdom);
+ }
+}
+
+static void verifyNoPointerSharing(IR::Function *function)
+{
+ if (!DoVerification)
+ return;
+
+ class {
+ public:
+ void operator()(IR::Function *f)
+ {
+ for (BasicBlock *bb : f->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+
+ for (Stmt *s : bb->statements()) {
+ visit(s);
+ }
+ }
+ }
+
+ private:
+ void visit(Stmt *s)
+ {
+ check(s);
+ STMT_VISIT_ALL_KINDS(s);
+ }
+
+ void visit(Expr *e)
+ {
+ check(e);
+ EXPR_VISIT_ALL_KINDS(e);
+ }
+
+ private:
+ void check(Stmt *s)
+ {
+ Q_ASSERT(!stmts.contains(s));
+ stmts.insert(s);
+ }
+
+ void check(Expr *e)
+ {
+ Q_ASSERT(!exprs.contains(e));
+ exprs.insert(e);
+ }
+
+ QSet<Stmt *> stmts;
+ QSet<Expr *> exprs;
+ } V;
+ V(function);
+}
+
// Loop-peeling is done by unfolding the loop once. The "original" loop basic blocks stay where they
// are, and a copy of the loop is placed after it. Special care is taken while copying the loop body:
// by having the copies of the basic-blocks point to the same nodes as the "original" basic blocks,
@@ -4826,12 +4977,14 @@ private:
void peelLoop(LoopDetection::LoopInfo *loop)
{
+ IR::Function *f = loop->loopHeader->function;
CloneBasicBlock clone;
LoopDetection::LoopInfo unpeeled(*loop);
unpeeled.loopHeader = clone(unpeeled.loopHeader);
unpeeled.loopHeader->setContainingGroup(loop->loopHeader->containingGroup());
unpeeled.loopHeader->markAsGroupStart(true);
+ f->addBasicBlock(unpeeled.loopHeader);
for (int i = 0, ei = unpeeled.loopBody.size(); i != ei; ++i) {
BasicBlock *&bodyBlock = unpeeled.loopBody[i];
bodyBlock = clone(bodyBlock);
@@ -4845,8 +4998,8 @@ private:
BasicBlock::IncomingEdges inCopy = loop->loopHeader->in;
for (BasicBlock *in : inCopy) {
- if (unpeeled.loopHeader != in // this can happen for really tight loops (where there are no body blocks). This is a back-edge in that case.
- && !unpeeled.loopBody.contains(in) // if the edge is not coming from within the copied set, leave it alone
+ if (loop->loopHeader != in // this can happen for really tight loops (where there are no body blocks). This is a back-edge in that case.
+ && unpeeled.loopHeader != in && !unpeeled.loopBody.contains(in) // if the edge is not coming from within the copied set, leave it alone
&& !dt.dominates(loop->loopHeader, in)) // an edge coming from within the loop (so a back-edge): this is handled when rewiring all outgoing edges
continue;
@@ -4876,9 +5029,7 @@ private:
loopExits.reserve(8);
loopExits.append(unpeeled.loopHeader);
- IR::Function *f = unpeeled.loopHeader->function;
rewire(unpeeled.loopHeader, loop->loopBody, unpeeled.loopBody, loopExits);
- f->addBasicBlock(unpeeled.loopHeader);
for (int i = 0, ei = unpeeled.loopBody.size(); i != ei; ++i) {
BasicBlock *bodyBlock = unpeeled.loopBody.at(i);
rewire(bodyBlock, loop->loopBody, unpeeled.loopBody, loopExits);
@@ -4891,6 +5042,9 @@ private:
for (BasicBlock *bb : qAsConst(loop->loopBody))
bb->setContainingGroup(loop->loopHeader->containingGroup());
+ // Set the immediate dominator of the new loop header to the old one. The real immediate
+ // dominator will be calculated later.
+ dt.setImmediateDominator(unpeeled.loopHeader, loop->loopHeader);
// calculate the idoms in a separate loop, because addBasicBlock in the previous loop will
// set the block index, which in turn is used by the dominator tree.
for (int i = 0, ei = unpeeled.loopBody.size(); i != ei; ++i) {
@@ -4909,141 +5063,13 @@ private:
for (BasicBlock *bb : qAsConst(loopExits))
dt.collectSiblings(bb, siblings);
+ siblings.insert(unpeeled.loopHeader);
dt.recalculateIDoms(siblings, loop->loopHeader);
+ dt.dumpImmediateDominators();
+ verifyImmediateDominators(dt, f);
}
};
-static void verifyCFG(IR::Function *function)
-{
- if (!DoVerification)
- return;
-
- for (BasicBlock *bb : function->basicBlocks()) {
- if (bb->isRemoved()) {
- Q_ASSERT(bb->in.isEmpty());
- Q_ASSERT(bb->out.isEmpty());
- continue;
- }
-
- Q_ASSERT(function->basicBlock(bb->index()) == bb);
-
- // Check the terminators:
- Stmt *terminator = bb->terminator();
- if (terminator == nullptr) {
- Stmt *last = bb->statements().last();
- Call *call = last->asExp()->expr->asCall();
- Name *baseName = call->base->asName();
- Q_ASSERT(baseName->builtin == Name::builtin_rethrow);
- Q_UNUSED(baseName);
- } else if (Jump *jump = terminator->asJump()) {
- Q_UNUSED(jump);
- Q_ASSERT(jump->target);
- Q_ASSERT(!jump->target->isRemoved());
- Q_ASSERT(bb->out.size() == 1);
- Q_ASSERT(bb->out.first() == jump->target);
- } else if (CJump *cjump = terminator->asCJump()) {
- Q_UNUSED(cjump);
- Q_ASSERT(bb->out.size() == 2);
- Q_ASSERT(cjump->iftrue);
- Q_ASSERT(!cjump->iftrue->isRemoved());
- Q_ASSERT(cjump->iftrue == bb->out[0]);
- Q_ASSERT(cjump->iffalse);
- Q_ASSERT(!cjump->iffalse->isRemoved());
- Q_ASSERT(cjump->iffalse == bb->out[1]);
- } else if (terminator->asRet()) {
- Q_ASSERT(bb->out.size() == 0);
- } else {
- Q_UNREACHABLE();
- }
-
- // Check the outgoing edges:
- for (BasicBlock *out : bb->out) {
- Q_UNUSED(out);
- Q_ASSERT(!out->isRemoved());
- Q_ASSERT(out->in.contains(bb));
- }
-
- // Check the incoming edges:
- for (BasicBlock *in : bb->in) {
- Q_UNUSED(in);
- Q_ASSERT(!in->isRemoved());
- Q_ASSERT(in->out.contains(bb));
- }
- }
-}
-
-static void verifyImmediateDominators(const DominatorTree &dt, IR::Function *function)
-{
- if (!DoVerification)
- return;
-
- cfg2dot(function);
- dt.dumpImmediateDominators();
- DominatorTree referenceTree(function);
-
- for (BasicBlock *bb : function->basicBlocks()) {
- if (bb->isRemoved())
- continue;
-
- BasicBlock *idom = dt.immediateDominator(bb);
- BasicBlock *referenceIdom = referenceTree.immediateDominator(bb);
- Q_UNUSED(idom);
- Q_UNUSED(referenceIdom);
- Q_ASSERT(idom == referenceIdom);
- }
-}
-
-static void verifyNoPointerSharing(IR::Function *function)
-{
- if (!DoVerification)
- return;
-
- class {
- public:
- void operator()(IR::Function *f)
- {
- for (BasicBlock *bb : f->basicBlocks()) {
- if (bb->isRemoved())
- continue;
-
- for (Stmt *s : bb->statements()) {
- visit(s);
- }
- }
- }
-
- private:
- void visit(Stmt *s)
- {
- check(s);
- STMT_VISIT_ALL_KINDS(s);
- }
-
- void visit(Expr *e)
- {
- check(e);
- EXPR_VISIT_ALL_KINDS(e);
- }
-
- private:
- void check(Stmt *s)
- {
- Q_ASSERT(!stmts.contains(s));
- stmts.insert(s);
- }
-
- void check(Expr *e)
- {
- Q_ASSERT(!exprs.contains(e));
- exprs.insert(e);
- }
-
- QSet<Stmt *> stmts;
- QSet<Expr *> exprs;
- } V;
- V(function);
-}
-
class RemoveLineNumbers: private SideEffectsChecker
{
public:
@@ -5452,6 +5478,9 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
verifyNoPointerSharing(function);
mergeBasicBlocks(function, &defUses, &df);
+ verifyImmediateDominators(df, function);
+ verifyCFG(function);
+
// Basic-block cycles that are unreachable (i.e. for loops in a then-part where the
// condition is calculated to be always false) are not yet removed. This will choke the
// block scheduling, so remove those now.
@@ -5459,10 +5488,13 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
cleanupBasicBlocks(function);
// showMeTheCode(function);
+ verifyImmediateDominators(df, function);
+ verifyCFG(function);
+
// Transform the CFG into edge-split SSA.
-// qout << "Starting edge splitting..." << endl;
+ showMeTheCode(function, "Before edge splitting");
splitCriticalEdges(function, df, worklist, defUses);
-// showMeTheCode(function);
+ showMeTheCode(function, "After edge splitting");
verifyImmediateDominators(df, function);
verifyCFG(function);
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index c2a5e75a1f..3abda68ae6 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -51,10 +51,6 @@
// We mean it.
//
-#if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
-#define V4_BOOTSTRAP
-#endif
-
#include <QtCore/qglobal.h>
#include <QString>
@@ -64,11 +60,11 @@
#define QML_NEARLY_ALWAYS_INLINE inline
#endif
-#ifdef V4_BOOTSTRAP
-#include <private/qtqmldevtoolsglobal_p.h>
-#else
#include <qtqmlglobal.h>
#include <private/qtqmlglobal_p.h>
+
+#ifdef QT_QML_BOOTSTRAPPED
+#define V4_BOOTSTRAP
#endif
#if defined(Q_CC_MSVC)
diff --git a/src/qml/qtqmlglobal.h b/src/qml/qtqmlglobal.h
index 89228b7777..6704e55b52 100644
--- a/src/qml/qtqmlglobal.h
+++ b/src/qml/qtqmlglobal.h
@@ -48,7 +48,11 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_STATIC
+#if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
+# define QT_QML_BOOTSTRAPPED
+#endif
+
+#if !defined(QT_QML_BOOTSTRAPPED) && !defined(QT_STATIC)
# if defined(QT_BUILD_QML_LIB)
# define Q_QML_EXPORT Q_DECL_EXPORT
# else
diff --git a/src/qml/qtqmlglobal_p.h b/src/qml/qtqmlglobal_p.h
index 026be5a703..6547274d09 100644
--- a/src/qml/qtqmlglobal_p.h
+++ b/src/qml/qtqmlglobal_p.h
@@ -63,7 +63,7 @@
Q_ALLOCA_DECLARE(type, name); \
Q_ALLOCA_ASSIGN(type, name, size)
-#if QT_CONFIG(alloca)
+#if defined(QT_BOOTSTRAPPED) || QT_CONFIG(alloca)
#define Q_ALLOCA_DECLARE(type, name) \
type *name = 0
@@ -95,10 +95,6 @@ QT_END_NAMESPACE
#endif
-#if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
-# define Q_QML_PRIVATE_EXPORT
-#else
-# define Q_QML_PRIVATE_EXPORT Q_QML_EXPORT
-#endif
+#define Q_QML_PRIVATE_EXPORT Q_QML_EXPORT
#endif // QTQMLGLOBAL_P_H
diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro
index ec5d73044f..a21988b915 100644
--- a/src/qmldevtools/qmldevtools.pro
+++ b/src/qmldevtools/qmldevtools.pro
@@ -1,11 +1,9 @@
option(host_build)
TARGET = QtQmlDevTools
QT = core-private
-CONFIG += static internal_module qmldevtools_build
+CONFIG += minimal_syncqt internal_module qmldevtools_build
-# Don't use pch because the auto-generated header refers to QtBootstrap,
-# which doesn't exist
-CONFIG -= precompile_header
+MODULE_INCNAME = QtQml
# 2415: variable "xx" of static storage duration was declared but never referenced
# unused variable 'xx' [-Werror,-Wunused-const-variable]
diff --git a/src/qmldevtools/qtqmldevtoolsglobal_p.h b/src/qmldevtools/qtqmldevtoolsglobal_p.h
deleted file mode 100644
index 5cb8a9275a..0000000000
--- a/src/qmldevtools/qtqmldevtoolsglobal_p.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTQMLGLOBAL_P_H
-#define QTQMLGLOBAL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-
-// All host systems are assumed to have alloca().
-#define Q_ALLOCA_VAR(type, name, size) \
- type *name = static_cast<type*>(alloca(size))
-
-QT_BEGIN_NAMESPACE
-
-#define Q_QML_EXPORT
-#define Q_QML_PRIVATE_EXPORT
-
-/* Some classes built into QtQmlDevTools are marked Q_AUTOTEST_EXPORT but we
- have nothing to export in this static library */
-#if defined(Q_AUTOTEST_EXPORT)
-#undef Q_AUTOTEST_EXPORT
-#endif
-#define Q_AUTOTEST_EXPORT
-
-QT_END_NAMESPACE
-#endif // QTQMLGLOBAL_P_H
diff --git a/sync.profile b/sync.profile
index 6cab0ae358..64abbd2eb9 100644
--- a/sync.profile
+++ b/sync.profile
@@ -4,12 +4,6 @@
"QtQuickWidgets" => "$basedir/src/quickwidgets",
"QtQuickParticles" => "$basedir/src/particles",
"QtQuickTest" => "$basedir/src/qmltest",
- "QtQmlDevTools" => "$basedir/src/qmldevtools",
"QtPacketProtocol" => "$basedir/src/plugins/qmltooling/packetprotocol",
"QtQmlDebug" => "$basedir/src/qmldebug",
);
-%moduleheaders = ( # restrict the module headers to those found in relative path
- "QtQmlDevTools" => "../qml/parser;../qml/jsruntime;../qml/qml/ftw;../qml/compiler;../qml/memory;.",
-);
-%deprecatedheaders = (
-);
diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_59012.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_59012.qml
new file mode 100644
index 0000000000..5283614435
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qtbug_59012.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+QtObject {
+ Component.onCompleted: {
+ var pieces = [[4,21],[6,22],[8,23],[12,24],[10,25],[8,26],[6,27],[4,28],[2,31],[2,32],[2,33],[2,35],[2,36],[2,37],[2,38],[2,54]]
+ var i = pieces.length;
+ var king = 10
+ var val
+ do {
+ var p = pieces[--i];
+ val = p[0]
+ } while (val !== king);
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index b5df8307c0..72179d243f 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -336,6 +336,7 @@ private slots:
void instanceof_data();
void instanceof();
void freeze_empty_object();
+ void singleBlockLoops();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -8240,6 +8241,14 @@ void tst_qqmlecmascript::freeze_empty_object()
QCOMPARE(v.toBool(), true);
}
+void tst_qqmlecmascript::singleBlockLoops()
+{
+ QQmlComponent component(&engine, testFileUrl("qtbug_59012.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj != 0);
+ QVERIFY(!component.isError());
+}
QTEST_MAIN(tst_qqmlecmascript)