Fix type checks for storage variable initializer.

This commit is contained in:
chriseth 2015-03-06 13:44:37 +01:00
parent 75b1151952
commit 28e88903dc
2 changed files with 25 additions and 27 deletions

51
AST.cpp
View File

@ -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<IntegerConstantType const>(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<IntegerConstantType const>(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();

1
AST.h
View File

@ -460,7 +460,6 @@ public:
virtual bool isLValue() const override;
/// Calls checkTypeRequirments for all state variables.
void checkTypeRequirements();
bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); }
bool isExternalFunctionParameter() const;