Merge pull request #10575 from ethereum/calldataArraySlices

Conversion of calldata array slices to memory
This commit is contained in:
chriseth
2020-12-15 12:21:33 +01:00
committed by GitHub
12 changed files with 158 additions and 25 deletions
+7 -3
View File
@@ -2074,9 +2074,13 @@ std::unique_ptr<ReferenceType> ArrayType::copyForLocation(DataLocation _location
BoolResult ArraySliceType::isImplicitlyConvertibleTo(Type const& _other) const
{
if (m_arrayType.location() == DataLocation::CallData && m_arrayType.isDynamicallySized() && m_arrayType == _other)
return true;
return (*this) == _other;
return
(*this) == _other ||
(
m_arrayType.dataStoredIn(DataLocation::CallData) &&
m_arrayType.isDynamicallySized() &&
m_arrayType.isImplicitlyConvertibleTo(_other)
);
}
string ArraySliceType::richIdentifier() const
+7 -7
View File
@@ -1050,18 +1050,18 @@ void CompilerUtils::convertType(
}
case Type::Category::ArraySlice:
{
solAssert(_targetType.category() == Type::Category::Array, "");
auto& typeOnStack = dynamic_cast<ArraySliceType const&>(_typeOnStack);
solUnimplementedAssert(
_targetType.dataStoredIn(DataLocation::CallData),
"Conversion from calldata slices to memory not yet implemented."
);
solAssert(_targetType == typeOnStack.arrayType(), "");
solUnimplementedAssert(
typeOnStack.arrayType().location() == DataLocation::CallData &&
auto const& targetArrayType = dynamic_cast<ArrayType const&>(_targetType);
solAssert(typeOnStack.arrayType().isImplicitlyConvertibleTo(targetArrayType), "");
solAssert(
typeOnStack.arrayType().dataStoredIn(DataLocation::CallData) &&
typeOnStack.arrayType().isDynamicallySized() &&
!typeOnStack.arrayType().baseType()->isDynamicallyEncoded(),
""
);
if (!_targetType.dataStoredIn(DataLocation::CallData))
return convertType(typeOnStack.arrayType(), _targetType);
break;
}
case Type::Category::Struct:
+10 -8
View File
@@ -2848,19 +2848,21 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
}
else if (_from.category() == Type::Category::ArraySlice)
{
solAssert(_from.isDynamicallySized(), "");
solAssert(_from.dataStoredIn(DataLocation::CallData), "");
solAssert(_to.category() == Type::Category::Array, "");
auto const& fromType = dynamic_cast<ArraySliceType const&>(_from);
auto const& targetType = dynamic_cast<ArrayType const&>(_to);
ArraySliceType const& fromType = dynamic_cast<ArraySliceType const&>(_from);
ArrayType const& targetType = dynamic_cast<ArrayType const&>(_to);
solAssert(!fromType.arrayType().baseType()->isDynamicallyEncoded(), "");
solAssert(fromType.arrayType().isImplicitlyConvertibleTo(targetType), "");
solAssert(
*fromType.arrayType().baseType() == *targetType.baseType(),
"Converting arrays of different type is not possible"
fromType.arrayType().dataStoredIn(DataLocation::CallData) &&
fromType.arrayType().isDynamicallySized() &&
!fromType.arrayType().baseType()->isDynamicallyEncoded(),
""
);
if (!targetType.dataStoredIn(DataLocation::CallData))
return arrayConversionFunction(fromType.arrayType(), targetType);
string const functionName =
"convert_" +
_from.identifier() +