aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-04-16 11:41:31 +0200
committerAapo Keskimolo <aapo.keskimolo@qt.io>2018-04-16 17:52:23 +0000
commitabe6c632161375df12a1ab73a9255486ba9436de (patch)
treef3858297e30a76f04dd0a11e566276ebb202e55f /src
parente8dec2a12b9bf3e1cad74c7387ad9a23c42e64d9 (diff)
Properly handle redeclarations of variables
This is only allowed for var type variables. Also fixes an assertion we'd run into with code such as let x; var x; Change-Id: I2588cf37e0964c879c60b4fd292e7d7b5476e322 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h43
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp28
2 files changed, 38 insertions, 33 deletions
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 8fabf41c40..455a76c729 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -257,29 +257,32 @@ struct Context {
usedVariables.insert(name);
}
- void addLocalVar(const QString &name, MemberType type, QQmlJS::AST::VariableDeclaration::VariableScope scope, QQmlJS::AST::FunctionExpression *function = nullptr)
+ bool addLocalVar(const QString &name, MemberType type, QQmlJS::AST::VariableDeclaration::VariableScope scope, QQmlJS::AST::FunctionExpression *function = nullptr)
{
- if (! name.isEmpty()) {
- if (type != FunctionDefinition) {
- for (QQmlJS::AST::FormalParameterList *it = formals; it; it = it->next)
- if (it->name == name)
- return;
- }
- MemberMap::iterator it = members.find(name);
- if (it == members.end()) {
- Member m;
- m.type = type;
- m.function = function;
- m.scope = scope;
- members.insert(name, m);
- } else {
- Q_ASSERT(scope == (*it).scope);
- if ((*it).type <= type) {
- (*it).type = type;
- (*it).function = function;
- }
+ if (name.isEmpty())
+ return true;
+
+ if (type != FunctionDefinition) {
+ for (QQmlJS::AST::FormalParameterList *it = formals; it; it = it->next)
+ if (it->name == name)
+ return (scope == QQmlJS::AST::VariableDeclaration::FunctionScope);
+ }
+ MemberMap::iterator it = members.find(name);
+ if (it != members.end()) {
+ if (scope != QQmlJS::AST::VariableDeclaration::FunctionScope || (*it).scope != QQmlJS::AST::VariableDeclaration::FunctionScope)
+ return false;
+ if ((*it).type <= type) {
+ (*it).type = type;
+ (*it).function = function;
}
+ return true;
}
+ Member m;
+ m.type = type;
+ m.function = function;
+ m.scope = scope;
+ members.insert(name, m);
+ return true;
}
};
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 92df98f201..84ee452332 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -215,14 +215,10 @@ bool ScanFunctions::visit(VariableDeclaration *ast)
return false;
}
QString name = ast->name.toString();
- const Context::Member *m = nullptr;
- if (_context->memberInfo(name, &m)) {
- if (m->isLexicallyScoped() || ast->isLexicallyScoped()) {
- _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Identifier %1 has already been declared").arg(name));
- return false;
- }
+ if (!_context->addLocalVar(ast->name.toString(), ast->expression ? Context::VariableDefinition : Context::VariableDeclaration, ast->scope)) {
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Identifier %1 has already been declared").arg(name));
+ return false;
}
- _context->addLocalVar(ast->name.toString(), ast->expression ? Context::VariableDefinition : Context::VariableDeclaration, ast->scope);
return true;
}
@@ -397,16 +393,22 @@ bool ScanFunctions::visit(Block *ast) {
void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr)
{
- if (_context) {
- _context->hasNestedFunctions = true;
+ Context *outerContext = _context;
+ enterEnvironment(ast, FunctionCode);
+
+ if (outerContext) {
+ outerContext->hasNestedFunctions = true;
// The identifier of a function expression cannot be referenced from the enclosing environment.
- if (expr)
- _context->addLocalVar(name, Context::FunctionDefinition, AST::VariableDeclaration::FunctionScope, expr);
+ if (expr) {
+ if (!outerContext->addLocalVar(name, Context::FunctionDefinition, AST::VariableDeclaration::FunctionScope, expr)) {
+ _cg->throwSyntaxError(ast->firstSourceLocation(), QStringLiteral("Identifier %1 has already been declared").arg(name));
+ return;
+ }
+ }
if (name == QLatin1String("arguments"))
- _context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
+ outerContext->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
}
- enterEnvironment(ast, FunctionCode);
if (formalsContainName(formals, QStringLiteral("arguments")))
_context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;