From 3bc78361d6923614b33728d287bf9822aa109a04 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 16 Apr 2015 00:06:57 +0200 Subject: [PATCH] Bugfixes concerning variable declarations. Fixes #1637 --- libsolidity/AST.cpp | 16 +++++++--------- libsolidity/Parser.cpp | 23 ++++++++++++----------- test/SolidityNameAndTypeResolution.cpp | 12 +++++++++++- test/SolidityParser.cpp | 9 +++++++++ 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 095ba7bf1..0abdf7819 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -378,20 +378,16 @@ void VariableDeclaration::checkTypeRequirements() if ((m_type && !m_type->isValueType()) || !m_value) BOOST_THROW_EXCEPTION(createTypeError("Unitialized \"constant\" variable.")); } - if (!m_value) - return; if (m_type) { - m_value->expectType(*m_type); - if (m_isStateVariable && !m_type->externalType() && getVisibility() >= Visibility::Public) - BOOST_THROW_EXCEPTION(createTypeError("Internal type is not allowed for state variables.")); - - if (!FunctionType(*this).externalType()) - BOOST_THROW_EXCEPTION(createTypeError("Internal type is not allowed for public state variables.")); + if (m_value) + m_value->expectType(*m_type); } else { - // no type declared and no previous assignment, infer the type + if (!m_value) + // This feature might be extended in the future. + BOOST_THROW_EXCEPTION(createTypeError("Assignment necessary for type detection.")); m_value->checkTypeRequirements(); TypePointer type = m_value->getType(); if (type->getCategory() == Type::Category::IntegerConstant) @@ -405,6 +401,8 @@ void VariableDeclaration::checkTypeRequirements() BOOST_THROW_EXCEPTION(createTypeError("Variable cannot have void type.")); m_type = type; } + if (m_isStateVariable && getVisibility() >= Visibility::Public && !FunctionType(*this).externalType()) + BOOST_THROW_EXCEPTION(createTypeError("Internal type is not allowed for public state variables.")); } bool VariableDeclaration::isExternalFunctionParameter() const diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 5c7676df5..43571314a 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -472,17 +472,18 @@ ASTPointer Parser::parseTypeName(bool _allowVar) else BOOST_THROW_EXCEPTION(createParserError("Expected type name")); - // Parse "[...]" postfixes for arrays. - while (m_scanner->getCurrentToken() == Token::LBrack) - { - m_scanner->next(); - ASTPointer length; - if (m_scanner->getCurrentToken() != Token::RBrack) - length = parseExpression(); - nodeFactory.markEndPosition(); - expectToken(Token::RBrack); - type = nodeFactory.createNode(type, length); - } + if (type) + // Parse "[...]" postfixes for arrays. + while (m_scanner->getCurrentToken() == Token::LBrack) + { + m_scanner->next(); + ASTPointer length; + if (m_scanner->getCurrentToken() != Token::RBrack) + length = parseExpression(); + nodeFactory.markEndPosition(); + expectToken(Token::RBrack); + type = nodeFactory.createNode(type, length); + } return type; } diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 74a488883..ffa78ed9e 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) { char const* text = "contract test {\n" " uint256 stateVariable1;\n" - " function fun(uint256 arg1) { var x; uint256 y; }" + " function fun(uint256 arg1) { uint256 y; }" "}\n"; ETH_TEST_CHECK_NO_THROW(parseTextAndResolveNames(text), "Parsing and Name Resolving Failed"); } @@ -1623,6 +1623,16 @@ BOOST_AUTO_TEST_CASE(bytes0_array) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(uninitialized_var) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint) { var x; return 2; } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index b76f00656..7cd8efce1 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -841,6 +841,15 @@ BOOST_AUTO_TEST_CASE(constant_is_keyword) BOOST_CHECK_THROW(parseText(text), ParserError); } +BOOST_AUTO_TEST_CASE(var_array) +{ + char const* text = R"( + contract Foo { + function f() { var[] a; } + })"; + BOOST_CHECK_THROW(parseText(text), ParserError); +} + BOOST_AUTO_TEST_SUITE_END() }