Merge pull request #54 from chriseth/sol_fixConstantStrings

Fix for constant strings.
This commit is contained in:
chriseth 2015-09-09 16:30:44 +02:00
commit 598696b641
4 changed files with 61 additions and 7 deletions

View File

@ -81,15 +81,16 @@ void ContractDefinition::checkTypeRequirements()
if (!function->isFullyImplemented())
setFullyImplemented(false);
}
for (ASTPointer<VariableDeclaration> const& variable: m_stateVariables)
variable->checkTypeRequirements();
for (ASTPointer<ModifierDefinition> const& modifier: functionModifiers())
modifier->checkTypeRequirements();
for (ASTPointer<FunctionDefinition> const& function: definedFunctions())
function->checkTypeRequirements();
for (ASTPointer<VariableDeclaration> const& variable: m_stateVariables)
variable->checkTypeRequirements();
checkExternalTypeClashes();
// check for hash collisions in function signatures
set<FixedHash<4>> hashes;
@ -559,9 +560,18 @@ void VariableDeclaration::checkTypeRequirements()
BOOST_THROW_EXCEPTION(createTypeError("Illegal use of \"constant\" specifier."));
if (!m_value)
BOOST_THROW_EXCEPTION(createTypeError("Uninitialized \"constant\" variable."));
else if (m_type && !m_type->isValueType())
// TODO: const is implemented only for uint, bytesXX and enums types.
BOOST_THROW_EXCEPTION(createTypeError("Illegal use of \"constant\" specifier. \"constant\" is not implemented for this type yet."));
if (m_type && !m_type->isValueType())
{
// TODO: const is implemented only for uint, bytesXX, string and enums types.
bool constImplemented = false;
if (auto arrayType = dynamic_cast<ArrayType const*>(m_type.get()))
constImplemented = arrayType->isByteArray();
if (!constImplemented)
BOOST_THROW_EXCEPTION(createTypeError(
"Illegal use of \"constant\" specifier. \"constant\" "
"is not yet implemented for this type."
));
}
}
if (m_type)
{

View File

@ -71,6 +71,7 @@ void ExpressionCompiler::appendConstStateVariableAccessor(VariableDeclaration co
{
solAssert(_varDecl.isConstant(), "");
_varDecl.value()->accept(*this);
utils().convertType(*_varDecl.value()->type(), *_varDecl.type());
// append return
m_context << eth::dupInstruction(_varDecl.type()->sizeOnStack() + 1);
@ -918,7 +919,10 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
if (!variable->isConstant())
setLValueFromDeclaration(*declaration, _identifier);
else
{
variable->value()->accept(*this);
utils().convertType(*variable->value()->type(), *variable->type());
}
}
else if (dynamic_cast<ContractDefinition const*>(declaration))
{

View File

@ -457,6 +457,14 @@ void ReferencesResolver::endVisit(VariableDeclaration& _variable)
}
else
{
if (_variable.isConstant())
{
if (loc != Location::Default && loc != Location::Memory)
BOOST_THROW_EXCEPTION(_variable.createTypeError(
"Storage location has to be \"memory\" (or unspecified) for constants."
));
loc = Location::Memory;
}
if (loc == Location::Default)
loc = _variable.isCallableParameter() ? Location::Memory : Location::Storage;
bool isPointer = !_variable.isStateVariable();

View File

@ -3700,7 +3700,7 @@ BOOST_AUTO_TEST_CASE(simple_constant_variables_test)
BOOST_AUTO_TEST_CASE(constant_variables)
{
//for now constant specifier is valid only for uint bytesXX and enums
//for now constant specifier is valid only for uint, bytesXX, string and enums
char const* sourceCode = R"(
contract Foo {
uint constant x = 56;
@ -5183,6 +5183,38 @@ BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable)
BOOST_CHECK(callContractFunction("ticketPrice()") == encodeArgs(u256(555)));
}
BOOST_AUTO_TEST_CASE(constant_string_literal)
{
char const* sourceCode = R"(
contract Test {
bytes32 constant public b = "abcdefghijklmnopq";
string constant public x = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca";
function Test() {
var xx = x;
var bb = b;
}
function getB() returns (bytes32) { return b; }
function getX() returns (string) { return x; }
function getX2() returns (string r) { r = x; }
function unused() returns (uint) {
"unusedunusedunusedunusedunusedunusedunusedunusedunusedunusedunusedunused";
return 2;
}
}
)";
compileAndRun(sourceCode);
string longStr = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca";
string shortStr = "abcdefghijklmnopq";
BOOST_CHECK(callContractFunction("b()") == encodeArgs(shortStr));
BOOST_CHECK(callContractFunction("x()") == encodeDyn(longStr));
BOOST_CHECK(callContractFunction("getB()") == encodeArgs(shortStr));
BOOST_CHECK(callContractFunction("getX()") == encodeDyn(longStr));
BOOST_CHECK(callContractFunction("getX2()") == encodeDyn(longStr));
BOOST_CHECK(callContractFunction("unused()") == encodeArgs(2));
}
BOOST_AUTO_TEST_CASE(storage_string_as_mapping_key_without_variable)
{
char const* sourceCode = R"(