Browse Source

- 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
cl-refactor
Liana Husikyan 10 years ago
parent
commit
7359f68b9f
  1. 7
      libsolidity/AST.cpp
  2. 1
      libsolidity/AST.h
  3. 6
      libsolidity/Parser.cpp
  4. 14
      test/SolidityEndToEndTest.cpp
  5. 34
      test/SolidityNameAndTypeResolution.cpp
  6. 1423
      test/SolidityNameAndTypeResolution.cpp.orig
  7. 9
      test/SolidityParser.cpp

7
libsolidity/AST.cpp

@ -332,6 +332,13 @@ void VariableDeclaration::checkTypeRequirements()
// sets the type.
// Note that assignments before the first declaration are legal because of the special scoping
// 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)
return;
if (m_type)

1
libsolidity/AST.h

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

6
libsolidity/Parser.cpp

@ -330,8 +330,11 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
}
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;
m_scanner->next();
}
nodeFactory.markEndPosition();
@ -920,6 +923,7 @@ Parser::LookAheadInfo Parser::peekStatementType() const
// In all other cases, we have an expression statement.
Token::Value token(m_scanner->getCurrentToken());
bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier);
if (token == Token::Mapping || token == Token::Var ||
(mightBeTypeName && m_scanner->peekNextToken() == Token::Identifier))
return LookAheadInfo::VariableDeclarationStatement;

14
test/SolidityEndToEndTest.cpp

@ -3196,26 +3196,28 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base_with_gap)
BOOST_CHECK(callContractFunction("m_i()") == encodeArgs(4));
}
BOOST_AUTO_TEST_CASE(constant_functions)
BOOST_AUTO_TEST_CASE(simple_constant_variables_test)
{
char const* sourceCode = R"(
contract Foo {
function getX() constant returns (uint r) { r = x; }
uint x = 56;
function getX() returns (uint r) { return x; }
uint constant x = 56;
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("getX()") == encodeArgs(56));
}
BOOST_AUTO_TEST_CASE(const_state_variable)
BOOST_AUTO_TEST_CASE(constant_variables)
{
//for now constant specifier is valid only for uint bytesXX and enums
char const* sourceCode = R"(
contract Foo {
function getX() constant returns (uint r) { return x; }
uint constant x = 56;
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
ActionChoices constant choices = ActionChoices.GoLeft;
bytes32 constant st = "abc\x00\xff__";
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("getX()") == encodeArgs(56));
}
BOOST_AUTO_TEST_SUITE_END()

34
test/SolidityNameAndTypeResolution.cpp

@ -1404,7 +1404,7 @@ BOOST_AUTO_TEST_CASE(test_byte_is_alias_of_byte1)
ETH_TEST_REQUIRE_NO_THROW(parseTextAndResolveNames(text), "Type resolving failed");
}
BOOST_AUTO_TEST_CASE(const_state_variable)
BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable)
{
char const* text = R"(
contract Foo {
@ -1414,6 +1414,38 @@ BOOST_AUTO_TEST_CASE(const_state_variable)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(complex_const_variable)
{
//for now constant specifier is valid only for uint bytesXX and enums
char const* text = R"(
contract Foo {
mapping(uint => bool) constant mapVar;
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(uninitialized_const_variable)
{
char const* text = R"(
contract Foo {
uint constant y;
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(local_const_variable)
{
char const* text = R"(
contract Foo {
function localConst() returns (uint ret)
{
uint constant local = 4;
return local;
}
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError);
}
BOOST_AUTO_TEST_SUITE_END()
}

1423
test/SolidityNameAndTypeResolution.cpp.orig

File diff suppressed because it is too large

9
test/SolidityParser.cpp

@ -822,6 +822,15 @@ BOOST_AUTO_TEST_CASE(multi_arrays)
ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed");
}
BOOST_AUTO_TEST_CASE(constant_is_keyword)
{
char const* text = R"(
contract Foo {
uint constant = 4;
})";
BOOST_CHECK_THROW(parseText(text), ParserError);
}
BOOST_AUTO_TEST_SUITE_END()
}

Loading…
Cancel
Save