Browse Source

Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop

cl-refactor
Gav Wood 9 years ago
parent
commit
14cf8af7ec
  1. 10
      libsolidity/AST.cpp
  2. 9
      libsolidity/CompilerUtils.cpp
  3. 14
      libsolidity/ExpressionCompiler.cpp
  4. 15
      libsolidity/Types.cpp
  5. 1
      libsolidity/Types.h
  6. 3
      test/libp2p/net.cpp
  7. 25
      test/libsolidity/SolidityEndToEndTest.cpp
  8. 17
      test/libsolidity/SolidityNameAndTypeResolution.cpp

10
libsolidity/AST.cpp

@ -844,9 +844,15 @@ void FunctionCall::checkTypeRequirements(TypePointers const*)
BOOST_THROW_EXCEPTION(createTypeError("Exactly one argument expected for explicit type conversion."));
if (!isPositionalCall)
BOOST_THROW_EXCEPTION(createTypeError("Type conversion cannot allow named arguments."));
if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType()))
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
m_type = type.getActualType();
auto argType = m_arguments.front()->getType();
if (auto argRefType = dynamic_cast<ReferenceType const*>(argType.get()))
// do not change the data location when converting
// (data location cannot yet be specified for type conversions)
m_type = ReferenceType::copyForLocationIfReference(argRefType->location(), m_type);
if (!argType->isExplicitlyConvertibleTo(*m_type))
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
return;
}

9
libsolidity/CompilerUtils.cpp

@ -404,7 +404,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
case DataLocation::Storage:
// Other cases are done explicitly in LValue::storeValue, and only possible by assignment.
solAssert(
targetType.isPointer() &&
(targetType.isPointer() || (typeOnStack.isByteArray() && targetType.isByteArray())) &&
typeOnStack.location() == DataLocation::Storage,
"Invalid conversion to storage type."
);
@ -469,6 +469,13 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
}
break;
}
case DataLocation::CallData:
solAssert(
targetType.isByteArray() &&
typeOnStack.isByteArray() &&
typeOnStack.location() == DataLocation::CallData,
"Invalid conversion to calldata type.");
break;
default:
solAssert(
false,

14
libsolidity/ExpressionCompiler.cpp

@ -807,16 +807,20 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
if (baseType.getCategory() == Type::Category::Mapping)
{
// stack: storage_base_ref
auto const& mapping = dynamic_cast<MappingType const&>(baseType);
Type const& keyType = *mapping.getKeyType();
TypePointer keyType = dynamic_cast<MappingType const&>(baseType).getKeyType();
solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
if (keyType.isDynamicallySized())
if (keyType->isDynamicallySized())
{
_indexAccess.getIndexExpression()->accept(*this);
utils().fetchFreeMemoryPointer();
// stack: base index mem
// note: the following operations must not allocate memory!
utils().encodeToMemory(TypePointers{mapping.getKeyType()}, TypePointers(), false, true);
utils().encodeToMemory(
TypePointers{_indexAccess.getIndexExpression()->getType()},
TypePointers{keyType},
false,
true
);
m_context << eth::Instruction::SWAP1;
utils().storeInMemoryDynamic(IntegerType(256));
utils().toSizeAfterFreeMemoryPointer();
@ -824,7 +828,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
else
{
m_context << u256(0); // memory position
appendExpressionCopyToMemory(keyType, *_indexAccess.getIndexExpression());
appendExpressionCopyToMemory(*keyType, *_indexAccess.getIndexExpression());
m_context << eth::Instruction::SWAP1;
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
utils().storeInMemoryDynamic(IntegerType(256));

15
libsolidity/Types.cpp

@ -789,6 +789,21 @@ bool ArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const
}
}
bool ArrayType::isExplicitlyConvertibleTo(const Type& _convertTo) const
{
if (isImplicitlyConvertibleTo(_convertTo))
return true;
// allow conversion bytes <-> string
if (_convertTo.getCategory() != getCategory())
return false;
auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
if (convertTo.location() != location())
return false;
if (!isByteArray() || !convertTo.isByteArray())
return false;
return true;
}
bool ArrayType::operator==(Type const& _other) const
{
if (_other.getCategory() != getCategory())

1
libsolidity/Types.h

@ -477,6 +477,7 @@ public:
{}
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool operator==(const Type& _other) const override;
virtual unsigned getCalldataEncodedSize(bool _padded) const override;
virtual bool isDynamicallySized() const override { return m_hasDynamicLength; }

3
test/libp2p/net.cpp

@ -339,6 +339,9 @@ BOOST_AUTO_TEST_SUITE(netTypes)
BOOST_AUTO_TEST_CASE(deadlineTimer)
{
// @subtly fixme
return;
if (test::Options::get().nonetwork)
return;

25
test/libsolidity/SolidityEndToEndTest.cpp

@ -5099,6 +5099,31 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0)));
}
BOOST_AUTO_TEST_CASE(string_bytes_conversion)
{
char const* sourceCode = R"(
contract Test {
string s;
bytes b;
function f(string _s, uint n) returns (byte) {
b = bytes(_s);
s = string(b);
return bytes(s)[n];
}
function l() returns (uint) { return bytes(s).length; }
}
)";
compileAndRun(sourceCode, 0, "Test");
BOOST_CHECK(callContractFunction(
"f(string,uint256)",
u256(0x40),
u256(2),
u256(6),
string("abcdef")
) == encodeArgs("c"));
BOOST_CHECK(callContractFunction("l()") == encodeArgs(u256(6)));
}
BOOST_AUTO_TEST_CASE(string_as_mapping_key)
{
char const* sourceCode = R"(

17
test/libsolidity/SolidityNameAndTypeResolution.cpp

@ -2149,6 +2149,23 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(string_bytes_conversion)
{
char const* text = R"(
contract Test {
string s;
bytes b;
function h(string _s) external { bytes(_s).length; }
function i(string _s) internal { bytes(_s).length; }
function j() internal { bytes(s).length; }
function k(bytes _b) external { string(_b); }
function l(bytes _b) internal { string(_b); }
function m() internal { string(b); }
}
)";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_SUITE_END()
}

Loading…
Cancel
Save