summaryrefslogtreecommitdiff
path: root/src/qml/compiler/qv4codegen.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-30 19:19:18 +0200
committerLars Knoll <lars.knoll@qt.io>2018-07-03 08:09:05 +0000
commit6d8dbba4624c8a453ba13ff009f011f2946422bb (patch)
treeec1aec45c122a31d7e5c1c19daa9ba5d4f824355 /src/qml/compiler/qv4codegen.cpp
parentdeaa99f66ddedc2ea79e6902c665925b04665e68 (diff)
downloadqtdeclarative-6d8dbba4624c8a453ba13ff009f011f2946422bb.tar.gz
Add support for super calls
Implement super call support for class constructor functions. Change-Id: I3c64276234689cf4f644b095e0fc8ca1c634ac53 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4codegen.cpp')
-rw-r--r--src/qml/compiler/qv4codegen.cpp97
1 files changed, 66 insertions, 31 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 40aac8f7bb..36f959b301 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1108,6 +1108,8 @@ bool Codegen::visit(ArrayMemberExpression *ast)
if (hasError)
return false;
base = base.storeOnStack();
+ if (hasError)
+ return false;
if (AST::StringLiteral *str = AST::cast<AST::StringLiteral *>(ast->expression)) {
QString s = str->value.toString();
uint arrayIndex = QV4::String::toArrayIndex(s);
@@ -1736,6 +1738,9 @@ bool Codegen::visit(CallExpression *ast)
break;
case Reference::Name:
break;
+ case Reference::Super:
+ handleConstruct(base, ast->arguments);
+ return false;
default:
base = base.storeOnStack();
break;
@@ -2015,12 +2020,12 @@ bool Codegen::visit(FalseLiteral *)
return false;
}
-bool Codegen::visit(SuperLiteral *ast)
+bool Codegen::visit(SuperLiteral *)
{
if (hasError)
return false;
- throwSyntaxError(ast->superToken, QLatin1String("Support for 'super' keyword not implemented"));
+ _expr.setResult(Reference::fromSuper(this));
return false;
}
@@ -2207,6 +2212,43 @@ bool Codegen::visit(NestedExpression *ast)
return false;
}
+void Codegen::handleConstruct(const Reference &base, ArgumentList *arguments)
+{
+ Reference constructor;
+ if (base.isSuper()) {
+ Instruction::LoadSuperConstructor super;
+ bytecodeGenerator->addInstruction(super);
+ constructor = Reference::fromAccumulator(this).storeOnStack();
+ } else {
+ constructor = base.storeOnStack();
+ }
+
+ auto calldata = pushArgs(arguments);
+ if (hasError)
+ return;
+
+ if (base.isSuper()) {
+ Reference::fromStackSlot(this, CallData::Function).loadInAccumulator();
+ } else {
+ constructor.loadInAccumulator();
+ }
+
+ if (calldata.hasSpread) {
+ Instruction::ConstructWithSpread create;
+ create.func = constructor.stackSlot();
+ create.argc = calldata.argc;
+ create.argv = calldata.argv;
+ bytecodeGenerator->addInstruction(create);
+ } else {
+ Instruction::Construct create;
+ create.func = constructor.stackSlot();
+ create.argc = calldata.argc;
+ create.argv = calldata.argv;
+ bytecodeGenerator->addInstruction(create);
+ }
+ _expr.setResult(Reference::fromAccumulator(this));
+}
+
bool Codegen::visit(NewExpression *ast)
{
if (hasError)
@@ -2217,16 +2259,12 @@ bool Codegen::visit(NewExpression *ast)
Reference base = expression(ast->expression);
if (hasError)
return false;
+ if (base.isSuper()) {
+ throwSyntaxError(ast->expression->firstSourceLocation(), QStringLiteral("Cannot use new with super."));
+ return false;
+ }
- base = base.storeOnStack();
- base.loadInAccumulator();
-
- Instruction::Construct create;
- create.func = base.stackSlot();
- create.argc = 0;
- create.argv = 0;
- bytecodeGenerator->addInstruction(create);
- _expr.setResult(Reference::fromAccumulator(this));
+ handleConstruct(base, nullptr);
return false;
}
@@ -2240,28 +2278,12 @@ bool Codegen::visit(NewMemberExpression *ast)
Reference base = expression(ast->base);
if (hasError)
return false;
- base = base.storeOnStack();
-
- auto calldata = pushArgs(ast->arguments);
- if (hasError)
+ if (base.isSuper()) {
+ throwSyntaxError(ast->base->firstSourceLocation(), QStringLiteral("Cannot use new with super."));
return false;
-
- base.loadInAccumulator();
-
- if (calldata.hasSpread) {
- Instruction::ConstructWithSpread create;
- create.func = base.stackSlot();
- create.argc = calldata.argc;
- create.argv = calldata.argv;
- bytecodeGenerator->addInstruction(create);
- } else {
- Instruction::Construct create;
- create.func = base.stackSlot();
- create.argc = calldata.argc;
- create.argv = calldata.argv;
- bytecodeGenerator->addInstruction(create);
}
- _expr.setResult(Reference::fromAccumulator(this));
+
+ handleConstruct(base, ast->arguments);
return false;
}
@@ -3684,6 +3706,8 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other)
case Invalid:
case Accumulator:
break;
+ case Super:
+ break;
case StackSlot:
theStackSlot = other.theStackSlot;
break;
@@ -3733,6 +3757,8 @@ bool Codegen::Reference::operator==(const Codegen::Reference &other) const
case Invalid:
case Accumulator:
break;
+ case Super:
+ return true;
case StackSlot:
return theStackSlot == other.theStackSlot;
case ScopedLocal:
@@ -3776,6 +3802,9 @@ Codegen::Reference Codegen::Reference::asLValue() const
case Invalid:
case Accumulator:
Q_UNREACHABLE();
+ case Super:
+ codegen->throwSyntaxError(AST::SourceLocation(), QStringLiteral("Super lvalues not implemented."));
+ return *this;
case Member:
if (!propertyBase.isStackSlot()) {
Reference r = *this;
@@ -3909,6 +3938,9 @@ void Codegen::Reference::storeAccumulator() const
return;
}
switch (type) {
+ case Super:
+ codegen->throwSyntaxError(SourceLocation(), QStringLiteral("storing super properties not implemented."));
+ return;
case StackSlot: {
Instruction::StoreReg store;
store.reg = theStackSlot;
@@ -3986,6 +4018,9 @@ void Codegen::Reference::loadInAccumulator() const
switch (type) {
case Accumulator:
return;
+ case Super:
+ codegen->throwSyntaxError(AST::SourceLocation(), QStringLiteral("Super property access not implemented."));
+ return;
case Const: {
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // the loads below are empty structs.