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.")); BOOST_THROW_EXCEPTION(createTypeError("Exactly one argument expected for explicit type conversion."));
if (!isPositionalCall) if (!isPositionalCall)
BOOST_THROW_EXCEPTION(createTypeError("Type conversion cannot allow named arguments.")); 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(); 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; return;
} }

9
libsolidity/CompilerUtils.cpp

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

14
libsolidity/ExpressionCompiler.cpp

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

1
libsolidity/Types.h

@ -477,6 +477,7 @@ public:
{} {}
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; 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 bool operator==(const Type& _other) const override;
virtual unsigned getCalldataEncodedSize(bool _padded) const override; virtual unsigned getCalldataEncodedSize(bool _padded) const override;
virtual bool isDynamicallySized() const override { return m_hasDynamicLength; } 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) BOOST_AUTO_TEST_CASE(deadlineTimer)
{ {
// @subtly fixme
return;
if (test::Options::get().nonetwork) if (test::Options::get().nonetwork)
return; 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_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) BOOST_AUTO_TEST_CASE(string_as_mapping_key)
{ {
char const* sourceCode = R"( 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_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() BOOST_AUTO_TEST_SUITE_END()
} }

Loading…
Cancel
Save