diff --git a/AST.cpp b/AST.cpp index 3a0aed119..79b755e97 100644 --- a/AST.cpp +++ b/AST.cpp @@ -328,8 +328,30 @@ bool VariableDeclaration::isLValue() const void VariableDeclaration::checkTypeRequirements() { - if (m_value) + // Variables can be declared without type (with "var"), in which case the first assignment + // sets the type. + // Note that assignments before the first declaration are legal because of the special scoping + // rules inherited from JavaScript. + if (!m_value) + return; + if (m_type) + m_value->expectType(*m_type); + else + { + // no type declared and no previous assignment, infer the type m_value->checkTypeRequirements(); + TypePointer type = m_value->getType(); + if (type->getCategory() == Type::Category::IntegerConstant) + { + auto intType = dynamic_pointer_cast(type)->getIntegerType(); + if (!intType) + BOOST_THROW_EXCEPTION(m_value->createTypeError("Invalid integer constant " + type->toString() + ".")); + type = intType; + } + else if (type->getCategory() == Type::Category::Void) + BOOST_THROW_EXCEPTION(createTypeError("Variable cannot have void type.")); + m_type = type; + } } bool VariableDeclaration::isExternalFunctionParameter() const @@ -445,32 +467,9 @@ void Return::checkTypeRequirements() void VariableDeclarationStatement::checkTypeRequirements() { - // Variables can be declared without type (with "var"), in which case the first assignment - // sets the type. - // Note that assignments before the first declaration are legal because of the special scoping - // rules inherited from JavaScript. - if (m_variable->getValue()) - { - if (m_variable->getType()) - m_variable->getValue()->expectType(*m_variable->getType()); - else - { - // no type declared and no previous assignment, infer the type - m_variable->getValue()->checkTypeRequirements(); - TypePointer type = m_variable->getValue()->getType(); - if (type->getCategory() == Type::Category::IntegerConstant) - { - auto intType = dynamic_pointer_cast(type)->getIntegerType(); - if (!intType) - BOOST_THROW_EXCEPTION(m_variable->getValue()->createTypeError("Invalid integer constant " + type->toString())); - type = intType; - } - else if (type->getCategory() == Type::Category::Void) - BOOST_THROW_EXCEPTION(m_variable->createTypeError("var cannot be void type")); - m_variable->setType(type); - } - } + m_variable->checkTypeRequirements(); } + void Assignment::checkTypeRequirements() { m_leftHandSide->checkTypeRequirements(); diff --git a/AST.h b/AST.h index c3c2cd8d3..eab53153f 100644 --- a/AST.h +++ b/AST.h @@ -460,7 +460,6 @@ public: virtual bool isLValue() const override; - /// Calls checkTypeRequirments for all state variables. void checkTypeRequirements(); bool isLocalVariable() const { return !!dynamic_cast(getScope()); } bool isExternalFunctionParameter() const;