Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix AND expression in v4
The type of the and expressions, e.g. (a && b), were being assigned
to the type of the right hand expression (b). As reported in
QTBUG-24660, this approach could lead to some unexpected behaviors.

Now, when the left and right hand expressions are of different types,
the responsability to deal with the and expression is delegated to v8.

Task-number: QTBUG-24660
Change-Id: Ic42ebb035e62e2f197c337b2106d00453a99f04c
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
  • Loading branch information
luisgabriel authored and Qt by Nokia committed Mar 14, 2012
1 parent 4cd2f0b commit b7f3138
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 3 deletions.
12 changes: 9 additions & 3 deletions src/qml/qml/v4/qv4irbuilder.cpp
Expand Up @@ -911,22 +911,28 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
IR::BasicBlock *iffalse = _function->newBasicBlock();
IR::BasicBlock *endif = _function->newBasicBlock();

condition(ast->left, iftrue, iffalse);
ExprResult left = expression(ast->left);
IR::Temp *cond = _block->TEMP(IR::BoolType);
_block->MOVE(cond, left);
_block->CJUMP(cond, iftrue, iffalse);

IR::Temp *r = _block->TEMP(IR::InvalidType);

_block = iffalse;
_block->MOVE(r, _block->CONST(IR::BoolType, 0)); // ### use the right null value
_block->MOVE(r, cond);
_block->JUMP(endif);

_block = iftrue;
ExprResult right = expression(ast->right);
_block->MOVE(r, right);
_block->JUMP(endif);

if (left.type() != right.type())
discard();

_block = endif;

r->type = right.type(); // ### not exactly, it can be IR::BoolType.
r->type = right.type();
_expr.code = r;
}
} break;
Expand Down
6 changes: 6 additions & 0 deletions tests/auto/qml/v4/data/logicalAnd.2.qml
@@ -0,0 +1,6 @@
import Qt.v4 1.0

Result {
property string s: "foo" && "bar"
result: s == "bar"
}
8 changes: 8 additions & 0 deletions tests/auto/qml/v4/data/logicalAnd.3.qml
@@ -0,0 +1,8 @@
import Qt.v4 1.0

Result {
property string s: ""
property bool flag: true

result: (s && flag) == ""
}
8 changes: 8 additions & 0 deletions tests/auto/qml/v4/data/logicalAnd.4.qml
@@ -0,0 +1,8 @@
import Qt.v4 1.0

Result {
property string s: "foo"
property bool flag: true

result: (!flag && s) == false
}
7 changes: 7 additions & 0 deletions tests/auto/qml/v4/data/logicalAnd.5.qml
@@ -0,0 +1,7 @@
import Qt.v4 1.0

Result {
property bool flag: true

result: (null && flag) == null
}
9 changes: 9 additions & 0 deletions tests/auto/qml/v4/data/logicalAnd.6.qml
@@ -0,0 +1,9 @@
import Qt.v4 1.0

Result {
property string s: ""
property bool flag: true
property string subresult: s && flag

result: subresult === ""
}
9 changes: 9 additions & 0 deletions tests/auto/qml/v4/data/logicalAnd.7.qml
@@ -0,0 +1,9 @@
import Qt.v4 1.0

Result {
property real nan: Number.NaN
property bool flag: true
property real subresult: nan && flag

result: isNaN(subresult)
}
6 changes: 6 additions & 0 deletions tests/auto/qml/v4/data/logicalAnd.qml
@@ -0,0 +1,6 @@
import Qt.v4 1.0

Result {
property int a: 10
result: a == 10 && a == 2
}
14 changes: 14 additions & 0 deletions tests/auto/qml/v4/data/nestedLogicalAnd.qml
@@ -0,0 +1,14 @@
import Qt.v4 1.0

Result {
property bool val1: false
property bool val2: true
property bool val3: false

property bool b1: (true && true && false)
property bool b2: (true && (false && true))
property bool b3: ((true && true) && true)
property bool b4: (val1 && (val2 && val3)) ? true : false

result: !b1 && !b2 && b3 && !b4
}
111 changes: 111 additions & 0 deletions tests/auto/qml/v4/tst_v4.cpp
Expand Up @@ -64,6 +64,8 @@ private slots:
void unnecessaryReeval();
void logicalOr();
void nestedLogicalOr();
void logicalAnd();
void nestedLogicalAnd();
void conditionalExpr();
void qtscript();
void qtscript_data();
Expand Down Expand Up @@ -208,6 +210,115 @@ void tst_v4::nestedLogicalOr()
delete o;
}

void tst_v4::logicalAnd()
{
{
QQmlComponent component(&engine, testFileUrl("logicalAnd.qml"));

QObject *o = component.create();
QVERIFY(o != 0);

ResultObject *ro = qobject_cast<ResultObject *>(o);
QVERIFY(ro != 0);

QCOMPARE(ro->result(), 0);
delete o;
}

{
QQmlComponent component(&engine, testFileUrl("logicalAnd.2.qml"));

QObject *o = component.create();
QVERIFY(o != 0);

ResultObject *ro = qobject_cast<ResultObject *>(o);
QVERIFY(ro != 0);

QCOMPARE(ro->result(), 1);
delete o;
}

{
QQmlComponent component(&engine, testFileUrl("logicalAnd.3.qml"));

QObject *o = component.create();
QVERIFY(o != 0);

ResultObject *ro = qobject_cast<ResultObject *>(o);
QVERIFY(ro != 0);

QCOMPARE(ro->result(), 1);
delete o;
}

{
// QTBUG-24660
QQmlComponent component(&engine, testFileUrl("logicalAnd.4.qml"));

QObject *o = component.create();
QVERIFY(o != 0);

ResultObject *ro = qobject_cast<ResultObject *>(o);
QVERIFY(ro != 0);

QCOMPARE(ro->result(), 1);
delete o;
}

{
QQmlComponent component(&engine, testFileUrl("logicalAnd.5.qml"));

QObject *o = component.create();
QVERIFY(o != 0);

ResultObject *ro = qobject_cast<ResultObject *>(o);
QVERIFY(ro != 0);

QCOMPARE(ro->result(), 1);
delete o;
}

{
QQmlComponent component(&engine, testFileUrl("logicalAnd.6.qml"));

QObject *o = component.create();
QVERIFY(o != 0);

ResultObject *ro = qobject_cast<ResultObject *>(o);
QVERIFY(ro != 0);

QCOMPARE(ro->result(), 1);
delete o;
}

{
QQmlComponent component(&engine, testFileUrl("logicalAnd.7.qml"));

QObject *o = component.create();
QVERIFY(o != 0);

ResultObject *ro = qobject_cast<ResultObject *>(o);
QVERIFY(ro != 0);

QCOMPARE(ro->result(), 1);
delete o;
}
}

void tst_v4::nestedLogicalAnd()
{
QQmlComponent component(&engine, testFileUrl("nestedLogicalAnd.qml"));

QObject *o = component.create();
QVERIFY(o != 0);

ResultObject *ro = qobject_cast<ResultObject *>(o);
QVERIFY(ro != 0);

QCOMPARE(ro->result(), 1);
delete o;
}

void tst_v4::conditionalExpr()
{
{
Expand Down

0 comments on commit b7f3138

Please sign in to comment.