mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #54 from chriseth/sol_fixConstantStrings
Fix for constant strings.
This commit is contained in:
commit
598696b641
@ -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)
|
||||
{
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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"(
|
||||
|
Loading…
Reference in New Issue
Block a user