diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 508b74497..731d432d2 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -3391,7 +3391,11 @@ string YulUtilFunctions::copyStructToStorageFunction(StructType const& _from, St string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayType const& _to) { - solAssert(_to.location() != DataLocation::CallData, ""); + if (_to.dataStoredIn(DataLocation::CallData)) + solAssert( + _from.dataStoredIn(DataLocation::CallData) && _from.isByteArray() && _to.isByteArray(), + "" + ); // Other cases are done explicitly in LValue::storeValue, and only possible by assignment. if (_to.location() == DataLocation::Storage) @@ -3409,16 +3413,22 @@ string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayTy return m_functionCollector.createFunction(functionName, [&]() { Whiskers templ(R"( - function (value, length) -> converted { + function (value, length) -> converted , outLength { + + outLength := + } )"); templ("functionName", functionName); templ("fromCalldataDynamic", _from.dataStoredIn(DataLocation::CallData) && _from.isDynamicallySized()); + templ("toCalldataDynamic", _to.dataStoredIn(DataLocation::CallData) && _to.isDynamicallySized()); + templ("length", _from.isDynamicallySized() ? "length" : _from.length().str()); if ( _from == _to || (_from.dataStoredIn(DataLocation::Memory) && _to.dataStoredIn(DataLocation::Memory)) || + (_from.dataStoredIn(DataLocation::CallData) && _to.dataStoredIn(DataLocation::CallData)) || _to.dataStoredIn(DataLocation::Storage) ) templ("body", "converted := value"); diff --git a/test/libsolidity/semanticTests/array/copying/bytes_calldata_to_string_calldata.sol b/test/libsolidity/semanticTests/array/copying/bytes_calldata_to_string_calldata.sol new file mode 100644 index 000000000..0d124f930 --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/bytes_calldata_to_string_calldata.sol @@ -0,0 +1,9 @@ +contract C { + function f(bytes calldata c) public returns (string calldata s) { + return string(c); + } +} +// ==== +// compileViaYul: also +// ---- +// f(bytes): 0x20, 3, "abc" -> 0x20, 3, "abc" diff --git a/test/libsolidity/semanticTests/array/copying/string_calldata_to_bytes_calldata.sol b/test/libsolidity/semanticTests/array/copying/string_calldata_to_bytes_calldata.sol new file mode 100644 index 000000000..04a125753 --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/string_calldata_to_bytes_calldata.sol @@ -0,0 +1,9 @@ +contract C { + function f(string calldata s) public returns (bytes calldata m) { + return bytes(s); + } +} +// ==== +// compileViaYul: also +// ---- +// f(string): 0x20, 3, "abc" -> 0x20, 3, "abc"