- added more tests to check constant specifier implementation

- deny use of const for local variables
- deny unitialized const variables
- only int, fixed strings, and enums can be declaired as const
This commit is contained in:
Liana Husikyan 2015-03-13 18:16:04 +01:00
parent 7d6357ae53
commit ebb4d5e298
3 changed files with 12 additions and 2 deletions

View File

@ -332,6 +332,13 @@ void VariableDeclaration::checkTypeRequirements()
// sets the type. // sets the type.
// Note that assignments before the first declaration are legal because of the special scoping // Note that assignments before the first declaration are legal because of the special scoping
// rules inherited from JavaScript. // rules inherited from JavaScript.
if (m_isConstant)
{
if (!dynamic_cast<ContractDefinition const*>(getScope()))
BOOST_THROW_EXCEPTION(createTypeError("Illegal use of \"constant\" specifier."));
if ((m_type && !m_type->isValueType()) || !m_value)
BOOST_THROW_EXCEPTION(createTypeError("Unitialized \"constant\" variable."));
}
if (!m_value) if (!m_value)
return; return;
if (m_type) if (m_type)

1
AST.h
View File

@ -472,7 +472,6 @@ public:
virtual bool isLValue() const override; virtual bool isLValue() const override;
virtual bool isPartOfExternalInterface() const override { return isPublic() && !m_isConstant; } virtual bool isPartOfExternalInterface() const override { return isPublic() && !m_isConstant; }
void checkTypeRequirements(); void checkTypeRequirements();
bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); } bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); }
bool isExternalFunctionParameter() const; bool isExternalFunctionParameter() const;

View File

@ -330,8 +330,11 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
} }
if (token == Token::Const) if (token == Token::Const)
{ {
m_scanner->next(); solAssert(_options.isStateVariable, "");
if (m_scanner->peekNextToken() != Token::Identifier && !Token::isElementaryTypeName(m_scanner->peekNextToken()))
BOOST_THROW_EXCEPTION(createParserError("Invalid use of \"constant\" specifier"));
isDeclaredConst = true; isDeclaredConst = true;
m_scanner->next();
} }
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
@ -920,6 +923,7 @@ Parser::LookAheadInfo Parser::peekStatementType() const
// In all other cases, we have an expression statement. // In all other cases, we have an expression statement.
Token::Value token(m_scanner->getCurrentToken()); Token::Value token(m_scanner->getCurrentToken());
bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier); bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier);
if (token == Token::Mapping || token == Token::Var || if (token == Token::Mapping || token == Token::Var ||
(mightBeTypeName && m_scanner->peekNextToken() == Token::Identifier)) (mightBeTypeName && m_scanner->peekNextToken() == Token::Identifier))
return LookAheadInfo::VariableDeclarationStatement; return LookAheadInfo::VariableDeclarationStatement;