Changed occurences of isByteArray() to isByteArrayOrString(). The idea

is to, in a future commit, replace such occurences of
isByteArrayOrString() which are required to return True only for Bytes
type with a new isByteArray() function.
This commit is contained in:
nishant-sachdeva 2022-01-28 23:27:05 +05:30
parent a05d2b356a
commit 9043621747
15 changed files with 120 additions and 120 deletions

View File

@ -441,7 +441,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
{ {
bool allowed = false; bool allowed = false;
if (auto arrayType = dynamic_cast<ArrayType const*>(type)) if (auto arrayType = dynamic_cast<ArrayType const*>(type))
allowed = arrayType->isByteArray(); allowed = arrayType->isByteArrayOrString();
if (!allowed) if (!allowed)
m_errorReporter.fatalTypeError(9259_error, _variable.location(), "Only constants of value type and byte array type are implemented."); m_errorReporter.fatalTypeError(9259_error, _variable.location(), "Only constants of value type and byte array type are implemented.");
} }

View File

@ -1783,7 +1783,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
( (
( (
resultArrayType->isPointer() || resultArrayType->isPointer() ||
(argArrayType->isByteArray() && resultArrayType->isByteArray()) (argArrayType->isByteArrayOrString() && resultArrayType->isByteArrayOrString())
) && ) &&
resultArrayType->location() == DataLocation::Storage resultArrayType->location() == DataLocation::Storage
), ),
@ -1791,7 +1791,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
); );
else else
solAssert( solAssert(
argArrayType->isByteArray() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes, argArrayType->isByteArrayOrString() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes,
"" ""
); );
} }

View File

@ -1206,7 +1206,7 @@ BoolResult StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo)
); );
return return
arrayType->location() != DataLocation::CallData && arrayType->location() != DataLocation::CallData &&
arrayType->isByteArray() && arrayType->isByteArrayOrString() &&
!(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer()); !(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer());
} }
else else
@ -1530,7 +1530,7 @@ BoolResult ArrayType::isImplicitlyConvertibleTo(Type const& _convertTo) const
if (_convertTo.category() != category()) if (_convertTo.category() != category())
return false; return false;
auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo); auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
if (convertTo.isByteArray() != isByteArray() || convertTo.isString() != isString()) if (convertTo.isByteArrayOrString() != isByteArrayOrString() || convertTo.isString() != isString())
return false; return false;
// memory/calldata to storage can be converted, but only to a direct storage reference // memory/calldata to storage can be converted, but only to a direct storage reference
if (convertTo.location() == DataLocation::Storage && location() != DataLocation::Storage && convertTo.isPointer()) if (convertTo.location() == DataLocation::Storage && location() != DataLocation::Storage && convertTo.isPointer())
@ -1571,11 +1571,11 @@ BoolResult ArrayType::isExplicitlyConvertibleTo(Type const& _convertTo) const
return true; return true;
// allow conversion bytes <-> string and bytes -> bytesNN // allow conversion bytes <-> string and bytes -> bytesNN
if (_convertTo.category() != category()) if (_convertTo.category() != category())
return isByteArray() && !isString() && _convertTo.category() == Type::Category::FixedBytes; return isByteArrayOrString() && !isString() && _convertTo.category() == Type::Category::FixedBytes;
auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo); auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
if (convertTo.location() != location()) if (convertTo.location() != location())
return false; return false;
if (!isByteArray() || !convertTo.isByteArray()) if (!isByteArrayOrString() || !convertTo.isByteArrayOrString())
return false; return false;
return true; return true;
} }
@ -1585,7 +1585,7 @@ string ArrayType::richIdentifier() const
string id; string id;
if (isString()) if (isString())
id = "t_string"; id = "t_string";
else if (isByteArray()) else if (isByteArrayOrString())
id = "t_bytes"; id = "t_bytes";
else else
{ {
@ -1608,7 +1608,7 @@ bool ArrayType::operator==(Type const& _other) const
ArrayType const& other = dynamic_cast<ArrayType const&>(_other); ArrayType const& other = dynamic_cast<ArrayType const&>(_other);
if ( if (
!ReferenceType::operator==(other) || !ReferenceType::operator==(other) ||
other.isByteArray() != isByteArray() || other.isByteArrayOrString() != isByteArrayOrString() ||
other.isString() != isString() || other.isString() != isString() ||
other.isDynamicallySized() != isDynamicallySized() other.isDynamicallySized() != isDynamicallySized()
) )
@ -1751,7 +1751,7 @@ string ArrayType::toString(bool _short) const
string ret; string ret;
if (isString()) if (isString())
ret = "string"; ret = "string";
else if (isByteArray()) else if (isByteArrayOrString())
ret = "bytes"; ret = "bytes";
else else
{ {
@ -1770,7 +1770,7 @@ string ArrayType::canonicalName() const
string ret; string ret;
if (isString()) if (isString())
ret = "string"; ret = "string";
else if (isByteArray()) else if (isByteArrayOrString())
ret = "bytes"; ret = "bytes";
else else
{ {
@ -1784,7 +1784,7 @@ string ArrayType::canonicalName() const
string ArrayType::signatureInExternalFunction(bool _structsByName) const string ArrayType::signatureInExternalFunction(bool _structsByName) const
{ {
if (isByteArray()) if (isByteArrayOrString())
return canonicalName(); return canonicalName();
else else
{ {
@ -1899,7 +1899,7 @@ u256 ArrayType::memoryDataSize() const
{ {
solAssert(!isDynamicallySized(), ""); solAssert(!isDynamicallySized(), "");
solAssert(m_location == DataLocation::Memory, ""); solAssert(m_location == DataLocation::Memory, "");
solAssert(!isByteArray(), ""); solAssert(!isByteArrayOrString(), "");
bigint size = bigint(m_length) * m_baseType->memoryHeadSize(); bigint size = bigint(m_length) * m_baseType->memoryHeadSize();
solAssert(size <= numeric_limits<u256>::max(), "Array size does not fit u256."); solAssert(size <= numeric_limits<u256>::max(), "Array size does not fit u256.");
return u256(size); return u256(size);
@ -2701,7 +2701,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
} }
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType)) else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
{ {
if (arrayType->isByteArray()) if (arrayType->isByteArrayOrString())
// Return byte arrays as whole. // Return byte arrays as whole.
break; break;
returnType = arrayType->baseType(); returnType = arrayType->baseType();
@ -2720,7 +2720,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
if (member.type->category() != Category::Mapping) if (member.type->category() != Category::Mapping)
{ {
if (auto arrayType = dynamic_cast<ArrayType const*>(member.type)) if (auto arrayType = dynamic_cast<ArrayType const*>(member.type))
if (!arrayType->isByteArray()) if (!arrayType->isByteArrayOrString())
continue; continue;
m_returnParameterTypes.push_back(TypeProvider::withLocationIfReference( m_returnParameterTypes.push_back(TypeProvider::withLocationIfReference(
DataLocation::Memory, DataLocation::Memory,
@ -3813,7 +3813,7 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
} }
else if ( else if (
auto const* arrayType = dynamic_cast<ArrayType const*>(m_actualType); auto const* arrayType = dynamic_cast<ArrayType const*>(m_actualType);
arrayType && arrayType->isByteArray() arrayType && arrayType->isByteArrayOrString()
) )
members.emplace_back("concat", TypeProvider::function( members.emplace_back("concat", TypeProvider::function(
TypePointers{}, TypePointers{},

View File

@ -838,7 +838,7 @@ public:
BoolResult validForLocation(DataLocation _loc) const override; BoolResult validForLocation(DataLocation _loc) const override;
/// @returns true if this is a byte array or a string /// @returns true if this is a byte array or a string
bool isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; } bool isByteArrayOrString() const { return m_arrayKind != ArrayKind::Ordinary; }
/// @returns true if this is a string /// @returns true if this is a string
bool isString() const { return m_arrayKind == ArrayKind::String; } bool isString() const { return m_arrayKind == ArrayKind::String; }
Type const* baseType() const { solAssert(!!m_baseType, ""); return m_baseType; } Type const* baseType() const { solAssert(!!m_baseType, ""); return m_baseType; }
@ -849,11 +849,11 @@ public:
std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const override; std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const override;
/// The offset to advance in calldata to move from one array element to the next. /// The offset to advance in calldata to move from one array element to the next.
unsigned calldataStride() const { return isByteArray() ? 1 : m_baseType->calldataHeadSize(); } unsigned calldataStride() const { return isByteArrayOrString() ? 1 : m_baseType->calldataHeadSize(); }
/// The offset to advance in memory to move from one array element to the next. /// The offset to advance in memory to move from one array element to the next.
unsigned memoryStride() const { return isByteArray() ? 1 : m_baseType->memoryHeadSize(); } unsigned memoryStride() const { return isByteArrayOrString() ? 1 : m_baseType->memoryHeadSize(); }
/// The offset to advance in storage to move from one array element to the next. /// The offset to advance in storage to move from one array element to the next.
unsigned storageStride() const { return isByteArray() ? 1 : m_baseType->storageBytes(); } unsigned storageStride() const { return isByteArrayOrString() ? 1 : m_baseType->storageBytes(); }
void clearCache() const override; void clearCache() const override;

View File

@ -312,7 +312,7 @@ string ABIFunctions::abiEncodingFunction(
{ {
case DataLocation::CallData: case DataLocation::CallData:
if ( if (
fromArray->isByteArray() || fromArray->isByteArrayOrString() ||
*fromArray->baseType() == *TypeProvider::uint256() || *fromArray->baseType() == *TypeProvider::uint256() ||
*fromArray->baseType() == FixedBytesType(32) *fromArray->baseType() == FixedBytesType(32)
) )
@ -320,7 +320,7 @@ string ABIFunctions::abiEncodingFunction(
else else
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options); return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
case DataLocation::Memory: case DataLocation::Memory:
if (fromArray->isByteArray()) if (fromArray->isByteArrayOrString())
return abiEncodingFunctionMemoryByteArray(*fromArray, *toArray, _options); return abiEncodingFunctionMemoryByteArray(*fromArray, *toArray, _options);
else else
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options); return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
@ -448,7 +448,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
solAssert(fromArrayType.location() == DataLocation::CallData, ""); solAssert(fromArrayType.location() == DataLocation::CallData, "");
solAssert( solAssert(
fromArrayType.isByteArray() || fromArrayType.isByteArrayOrString() ||
*fromArrayType.baseType() == *TypeProvider::uint256() || *fromArrayType.baseType() == *TypeProvider::uint256() ||
*fromArrayType.baseType() == FixedBytesType(32), *fromArrayType.baseType() == FixedBytesType(32),
"" ""
@ -468,7 +468,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
_to.identifier() + _to.identifier() +
_options.toFunctionNameSuffix(); _options.toFunctionNameSuffix();
return createFunction(functionName, [&]() { return createFunction(functionName, [&]() {
bool needsPadding = _options.padded && fromArrayType.isByteArray(); bool needsPadding = _options.padded && fromArrayType.isByteArrayOrString();
if (fromArrayType.isDynamicallySized()) if (fromArrayType.isDynamicallySized())
{ {
Whiskers templ(R"( Whiskers templ(R"(
@ -482,7 +482,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
)"); )");
templ("storeLength", arrayStoreLengthForEncodingFunction(toArrayType, _options)); templ("storeLength", arrayStoreLengthForEncodingFunction(toArrayType, _options));
templ("functionName", functionName); templ("functionName", functionName);
if (fromArrayType.isByteArray() || fromArrayType.calldataStride() == 1) if (fromArrayType.isByteArrayOrString() || fromArrayType.calldataStride() == 1)
templ("scaleLengthByStride", ""); templ("scaleLengthByStride", "");
else else
templ("scaleLengthByStride", templ("scaleLengthByStride",
@ -536,7 +536,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), ""); solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), "");
solAssert(_from.length() == _to.length(), ""); solAssert(_from.length() == _to.length(), "");
solAssert(!_from.isByteArray(), ""); solAssert(!_from.isByteArrayOrString(), "");
if (_from.dataStoredIn(DataLocation::Storage)) if (_from.dataStoredIn(DataLocation::Storage))
solAssert(_from.baseType()->storageBytes() > 16, ""); solAssert(_from.baseType()->storageBytes() > 16, "");
@ -647,10 +647,10 @@ string ABIFunctions::abiEncodingFunctionMemoryByteArray(
solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), ""); solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), "");
solAssert(_from.length() == _to.length(), ""); solAssert(_from.length() == _to.length(), "");
solAssert(_from.dataStoredIn(DataLocation::Memory), ""); solAssert(_from.dataStoredIn(DataLocation::Memory), "");
solAssert(_from.isByteArray(), ""); solAssert(_from.isByteArrayOrString(), "");
return createFunction(functionName, [&]() { return createFunction(functionName, [&]() {
solAssert(_to.isByteArray(), ""); solAssert(_to.isByteArrayOrString(), "");
Whiskers templ(R"( Whiskers templ(R"(
function <functionName>(value, pos) -> end { function <functionName>(value, pos) -> end {
let length := <lengthFun>(value) let length := <lengthFun>(value)
@ -686,9 +686,9 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
solAssert(_from.dataStoredIn(DataLocation::Storage), ""); solAssert(_from.dataStoredIn(DataLocation::Storage), "");
return createFunction(functionName, [&]() { return createFunction(functionName, [&]() {
if (_from.isByteArray()) if (_from.isByteArrayOrString())
{ {
solAssert(_to.isByteArray(), ""); solAssert(_to.isByteArrayOrString(), "");
Whiskers templ(R"( Whiskers templ(R"(
// <readableTypeNameFrom> -> <readableTypeNameTo> // <readableTypeNameFrom> -> <readableTypeNameTo>
function <functionName>(value, pos) -> ret { function <functionName>(value, pos) -> ret {
@ -1168,7 +1168,7 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from
string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory) string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
{ {
solAssert(_type.dataStoredIn(DataLocation::Memory), ""); solAssert(_type.dataStoredIn(DataLocation::Memory), "");
if (_type.isByteArray()) if (_type.isByteArrayOrString())
return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory); return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory);
solAssert(_type.calldataStride() > 0, ""); solAssert(_type.calldataStride() > 0, "");
@ -1275,7 +1275,7 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory) string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
{ {
solAssert(_type.dataStoredIn(DataLocation::Memory), ""); solAssert(_type.dataStoredIn(DataLocation::Memory), "");
solAssert(_type.isByteArray(), ""); solAssert(_type.isByteArrayOrString(), "");
string functionName = string functionName =
"abi_decode_available_length_" + "abi_decode_available_length_" +

View File

@ -50,8 +50,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
solAssert(_targetType.location() == DataLocation::Storage, ""); solAssert(_targetType.location() == DataLocation::Storage, "");
Type const* uint256 = TypeProvider::uint256(); Type const* uint256 = TypeProvider::uint256();
Type const* targetBaseType = _targetType.isByteArray() ? uint256 : _targetType.baseType(); Type const* targetBaseType = _targetType.isByteArrayOrString() ? uint256 : _targetType.baseType();
Type const* sourceBaseType = _sourceType.isByteArray() ? uint256 : _sourceType.baseType(); Type const* sourceBaseType = _sourceType.isByteArrayOrString() ? uint256 : _sourceType.baseType();
// TODO unroll loop for small sizes // TODO unroll loop for small sizes
@ -97,7 +97,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// stack: target_ref source_ref source_length target_ref target_length // stack: target_ref source_ref source_length target_ref target_length
if (_targetType.isDynamicallySized()) if (_targetType.isDynamicallySized())
// store new target length // store new target length
if (!_targetType.isByteArray()) if (!_targetType.isByteArrayOrString())
// Otherwise, length will be stored below. // Otherwise, length will be stored below.
_context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE; _context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE;
if (sourceBaseType->category() == Type::Category::Mapping) if (sourceBaseType->category() == Type::Category::Mapping)
@ -126,7 +126,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
evmasm::AssemblyItem copyLoopEndWithoutByteOffset = _context.newTag(); evmasm::AssemblyItem copyLoopEndWithoutByteOffset = _context.newTag();
// special case for short byte arrays: Store them together with their length. // special case for short byte arrays: Store them together with their length.
if (_targetType.isByteArray()) if (_targetType.isByteArrayOrString())
{ {
// stack: target_ref target_data_end source_length target_data_pos source_ref // stack: target_ref target_data_end source_length target_data_pos source_ref
_context << Instruction::DUP3; _context << Instruction::DUP3;
@ -141,7 +141,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
_context << Instruction::DUP3 << u256(31) << Instruction::LT; _context << Instruction::DUP3 << u256(31) << Instruction::LT;
evmasm::AssemblyItem longByteArray = _context.appendConditionalJump(); evmasm::AssemblyItem longByteArray = _context.appendConditionalJump();
// store the short byte array // store the short byte array
solAssert(_sourceType.isByteArray(), ""); solAssert(_sourceType.isByteArrayOrString(), "");
if (_sourceType.location() == DataLocation::Storage) if (_sourceType.location() == DataLocation::Storage)
{ {
// just copy the slot, it contains length and data // just copy the slot, it contains length and data
@ -323,7 +323,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
{ {
if (!_sourceType.isDynamicallySized()) if (!_sourceType.isDynamicallySized())
m_context << _sourceType.length(); m_context << _sourceType.length();
if (!_sourceType.isByteArray()) if (!_sourceType.isByteArrayOrString())
convertLengthToSize(_sourceType); convertLengthToSize(_sourceType);
string routine = "calldatacopy(target, source, len)\n"; string routine = "calldatacopy(target, source, len)\n";
@ -375,14 +375,14 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
m_context << Instruction::SWAP1 << u256(32) << Instruction::ADD; m_context << Instruction::SWAP1 << u256(32) << Instruction::ADD;
m_context << Instruction::SWAP1; m_context << Instruction::SWAP1;
} }
if (!_sourceType.isByteArray()) if (!_sourceType.isByteArrayOrString())
convertLengthToSize(_sourceType); convertLengthToSize(_sourceType);
// stack: <target> <source> <size> // stack: <target> <source> <size>
m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::DUP4; m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::DUP4;
// We can resort to copying full 32 bytes only if // We can resort to copying full 32 bytes only if
// - the length is known to be a multiple of 32 or // - the length is known to be a multiple of 32 or
// - we will pad to full 32 bytes later anyway. // - we will pad to full 32 bytes later anyway.
if (!_sourceType.isByteArray() || _padToWordBoundaries) if (!_sourceType.isByteArrayOrString() || _padToWordBoundaries)
utils.memoryCopy32(); utils.memoryCopy32();
else else
utils.memoryCopy(); utils.memoryCopy();
@ -390,7 +390,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
m_context << Instruction::SWAP1 << Instruction::POP; m_context << Instruction::SWAP1 << Instruction::POP;
// stack: <target> <size> // stack: <target> <size>
bool paddingNeeded = _padToWordBoundaries && _sourceType.isByteArray(); bool paddingNeeded = _padToWordBoundaries && _sourceType.isByteArrayOrString();
if (paddingNeeded) if (paddingNeeded)
{ {
@ -446,7 +446,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
m_context << Instruction::DUP1 << Instruction::ISZERO; m_context << Instruction::DUP1 << Instruction::ISZERO;
evmasm::AssemblyItem loopEnd = m_context.appendConditionalJump(); evmasm::AssemblyItem loopEnd = m_context.appendConditionalJump();
// Special case for tightly-stored byte arrays // Special case for tightly-stored byte arrays
if (_sourceType.isByteArray()) if (_sourceType.isByteArrayOrString())
{ {
// stack here: memory_offset storage_offset length // stack here: memory_offset storage_offset length
m_context << Instruction::DUP1 << u256(31) << Instruction::LT; m_context << Instruction::DUP1 << u256(31) << Instruction::LT;
@ -482,14 +482,14 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
} }
// stack here: memory_end_offset storage_data_offset memory_offset // stack here: memory_end_offset storage_data_offset memory_offset
bool haveByteOffset = !_sourceType.isByteArray() && storageBytes <= 16; bool haveByteOffset = !_sourceType.isByteArrayOrString() && storageBytes <= 16;
if (haveByteOffset) if (haveByteOffset)
m_context << u256(0) << Instruction::SWAP1; m_context << u256(0) << Instruction::SWAP1;
// stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset // stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset
evmasm::AssemblyItem loopStart = m_context.newTag(); evmasm::AssemblyItem loopStart = m_context.newTag();
m_context << loopStart; m_context << loopStart;
// load and store // load and store
if (_sourceType.isByteArray()) if (_sourceType.isByteArrayOrString())
{ {
// Packed both in storage and memory. // Packed both in storage and memory.
m_context << Instruction::DUP2 << Instruction::SLOAD; m_context << Instruction::DUP2 << Instruction::SLOAD;
@ -528,12 +528,12 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
// stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset // stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset
if (haveByteOffset) if (haveByteOffset)
m_context << Instruction::SWAP1 << Instruction::POP; m_context << Instruction::SWAP1 << Instruction::POP;
if (!_sourceType.isByteArray()) if (!_sourceType.isByteArrayOrString())
{ {
solAssert(_sourceType.calldataStride() % 32 == 0, ""); solAssert(_sourceType.calldataStride() % 32 == 0, "");
solAssert(_sourceType.memoryStride() % 32 == 0, ""); solAssert(_sourceType.memoryStride() % 32 == 0, "");
} }
if (_padToWordBoundaries && _sourceType.isByteArray()) if (_padToWordBoundaries && _sourceType.isByteArrayOrString())
{ {
// memory_end_offset - start is the actual length (we want to compute the ceil of). // memory_end_offset - start is the actual length (we want to compute the ceil of).
// memory_offset - start is its next multiple of 32, but it might be off by 32. // memory_offset - start is its next multiple of 32, but it might be off by 32.
@ -624,7 +624,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
m_context << u256(0) << Instruction::DUP3 << Instruction::SSTORE; m_context << u256(0) << Instruction::DUP3 << Instruction::SSTORE;
// Special case: short byte arrays are stored togeher with their length // Special case: short byte arrays are stored togeher with their length
evmasm::AssemblyItem endTag = m_context.newTag(); evmasm::AssemblyItem endTag = m_context.newTag();
if (_type.isByteArray()) if (_type.isByteArrayOrString())
{ {
// stack: ref old_length // stack: ref old_length
m_context << Instruction::DUP1 << u256(31) << Instruction::LT; m_context << Instruction::DUP1 << u256(31) << Instruction::LT;
@ -664,7 +664,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
ArrayType const& _type = dynamic_cast<ArrayType const&>(*type); ArrayType const& _type = dynamic_cast<ArrayType const&>(*type);
solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), ""); solAssert(_type.isDynamicallySized(), "");
if (!_type.isByteArray() && _type.baseType()->storageBytes() < 32) if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32)
solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type."); solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type.");
unsigned stackHeightStart = _context.stackHeight(); unsigned stackHeightStart = _context.stackHeight();
@ -677,7 +677,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "2"); solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "2");
// Special case for short byte arrays, they are stored together with their length // Special case for short byte arrays, they are stored together with their length
if (_type.isByteArray()) if (_type.isByteArrayOrString())
{ {
evmasm::AssemblyItem regularPath = _context.newTag(); evmasm::AssemblyItem regularPath = _context.newTag();
// We start by a large case-distinction about the old and new length of the byte array. // We start by a large case-distinction about the old and new length of the byte array.
@ -766,7 +766,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
// stack: ref new_length old_length // stack: ref new_length old_length
// store new length // store new length
_context << Instruction::DUP2; _context << Instruction::DUP2;
if (_type.isByteArray()) if (_type.isByteArrayOrString())
// For a "long" byte array, store length as 2*length+1 // For a "long" byte array, store length as 2*length+1
_context << Instruction::DUP1 << Instruction::ADD << u256(1) << Instruction::ADD; _context << Instruction::DUP1 << Instruction::ADD << u256(1) << Instruction::ADD;
_context << Instruction::DUP4 << Instruction::SSTORE; _context << Instruction::DUP4 << Instruction::SSTORE;
@ -806,10 +806,10 @@ void ArrayUtils::incrementDynamicArraySize(ArrayType const& _type) const
{ {
solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), ""); solAssert(_type.isDynamicallySized(), "");
if (!_type.isByteArray() && _type.baseType()->storageBytes() < 32) if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32)
solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type."); solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type.");
if (_type.isByteArray()) if (_type.isByteArrayOrString())
{ {
// We almost always just add 2 (length of byte arrays is shifted left by one) // We almost always just add 2 (length of byte arrays is shifted left by one)
// except for the case where we transition from a short byte array // except for the case where we transition from a short byte array
@ -850,10 +850,10 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
{ {
solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), ""); solAssert(_type.isDynamicallySized(), "");
if (!_type.isByteArray() && _type.baseType()->storageBytes() < 32) if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32)
solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type."); solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type.");
if (_type.isByteArray()) if (_type.isByteArrayOrString())
{ {
m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::DUP1; m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::DUP1;
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1); m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
@ -999,7 +999,7 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con
} }
else else
{ {
if (!_arrayType.isByteArray()) if (!_arrayType.isByteArrayOrString())
{ {
if (_arrayType.location() == DataLocation::Memory) if (_arrayType.location() == DataLocation::Memory)
m_context << _arrayType.memoryStride(); m_context << _arrayType.memoryStride();
@ -1031,7 +1031,7 @@ void ArrayUtils::retrieveLength(ArrayType const& _arrayType, unsigned _stackDept
break; break;
case DataLocation::Storage: case DataLocation::Storage:
m_context << Instruction::SLOAD; m_context << Instruction::SLOAD;
if (_arrayType.isByteArray()) if (_arrayType.isByteArrayOrString())
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1); m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
break; break;
} }
@ -1062,7 +1062,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
{ {
case DataLocation::Memory: case DataLocation::Memory:
// stack: <base_ref> <index> // stack: <base_ref> <index>
if (!_arrayType.isByteArray()) if (!_arrayType.isByteArrayOrString())
m_context << u256(_arrayType.memoryHeadSize()) << Instruction::MUL; m_context << u256(_arrayType.memoryHeadSize()) << Instruction::MUL;
if (_arrayType.isDynamicallySized()) if (_arrayType.isDynamicallySized())
m_context << u256(32) << Instruction::ADD; m_context << u256(32) << Instruction::ADD;
@ -1071,7 +1071,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
m_context << Instruction::ADD; m_context << Instruction::ADD;
break; break;
case DataLocation::CallData: case DataLocation::CallData:
if (!_arrayType.isByteArray()) if (!_arrayType.isByteArrayOrString())
{ {
m_context << _arrayType.calldataStride(); m_context << _arrayType.calldataStride();
m_context << Instruction::MUL; m_context << Instruction::MUL;
@ -1090,7 +1090,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
// stack: [<base_ref>] <index> <base_ref> // stack: [<base_ref>] <index> <base_ref>
evmasm::AssemblyItem endTag = m_context.newTag(); evmasm::AssemblyItem endTag = m_context.newTag();
if (_arrayType.isByteArray()) if (_arrayType.isByteArrayOrString())
{ {
// Special case of short byte arrays. // Special case of short byte arrays.
m_context << Instruction::SWAP1; m_context << Instruction::SWAP1;
@ -1153,7 +1153,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d
{ {
solAssert(_arrayType.baseType()->storageBytes() <= 32, ""); solAssert(_arrayType.baseType()->storageBytes() <= 32, "");
if ( if (
!_arrayType.isByteArray() && !_arrayType.isByteArrayOrString() &&
_arrayType.baseType()->storageBytes() < 32 && _arrayType.baseType()->storageBytes() < 32 &&
m_context.useABICoderV2() m_context.useABICoderV2()
) )
@ -1165,7 +1165,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d
CompilerUtils(m_context).loadFromMemoryDynamic( CompilerUtils(m_context).loadFromMemoryDynamic(
*_arrayType.baseType(), *_arrayType.baseType(),
true, true,
!_arrayType.isByteArray(), !_arrayType.isByteArrayOrString(),
false false
); );
} }

View File

@ -970,7 +970,7 @@ void CompilerUtils::convertType(
else if (targetTypeCategory == Type::Category::Array) else if (targetTypeCategory == Type::Category::Array)
{ {
auto const& arrayType = dynamic_cast<ArrayType const&>(_targetType); auto const& arrayType = dynamic_cast<ArrayType const&>(_targetType);
solAssert(arrayType.isByteArray()); solAssert(arrayType.isByteArrayOrString());
size_t storageSize = 32 + ((data.size() + 31) / 32) * 32; size_t storageSize = 32 + ((data.size() + 31) / 32) * 32;
allocateMemory(storageSize); allocateMemory(storageSize);
// stack: mempos // stack: mempos
@ -992,7 +992,7 @@ void CompilerUtils::convertType(
if (_targetType.category() == Type::Category::FixedBytes) if (_targetType.category() == Type::Category::FixedBytes)
{ {
solAssert( solAssert(
typeOnStack.isByteArray() && !typeOnStack.isString(), typeOnStack.isByteArrayOrString() && !typeOnStack.isString(),
"Array types other than bytes not convertible to bytesNN." "Array types other than bytes not convertible to bytesNN."
); );
solAssert(typeOnStack.isDynamicallySized()); solAssert(typeOnStack.isDynamicallySized());
@ -1019,7 +1019,7 @@ void CompilerUtils::convertType(
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() || (typeOnStack.isByteArray() && targetType.isByteArray())) && (targetType.isPointer() || (typeOnStack.isByteArrayOrString() && targetType.isByteArrayOrString())) &&
typeOnStack.location() == DataLocation::Storage, typeOnStack.location() == DataLocation::Storage,
"Invalid conversion to storage type." "Invalid conversion to storage type."
); );
@ -1105,7 +1105,7 @@ void CompilerUtils::convertType(
} }
case DataLocation::CallData: case DataLocation::CallData:
solAssert( solAssert(
((targetType.isByteArray() && typeOnStack.isByteArray()) || _typeOnStack == _targetType) && ((targetType.isByteArrayOrString() && typeOnStack.isByteArrayOrString()) || _typeOnStack == _targetType) &&
typeOnStack.location() == DataLocation::CallData, typeOnStack.location() == DataLocation::CallData,
"Invalid conversion to calldata type." "Invalid conversion to calldata type."
); );
@ -1119,7 +1119,7 @@ void CompilerUtils::convertType(
if (_targetType.category() == Type::Category::FixedBytes) if (_targetType.category() == Type::Category::FixedBytes)
{ {
solAssert( solAssert(
typeOnStack.arrayType().isByteArray() && !typeOnStack.arrayType().isString(), typeOnStack.arrayType().isByteArrayOrString() && !typeOnStack.arrayType().isString(),
"Array types other than bytes not convertible to bytesNN." "Array types other than bytes not convertible to bytesNN."
); );
solAssert(typeOnStack.isDynamicallySized()); solAssert(typeOnStack.isDynamicallySized());
@ -1142,7 +1142,7 @@ void CompilerUtils::convertType(
auto const& targetArrayType = dynamic_cast<ArrayType const&>(_targetType); auto const& targetArrayType = dynamic_cast<ArrayType const&>(_targetType);
solAssert( solAssert(
typeOnStack.arrayType().isImplicitlyConvertibleTo(targetArrayType) || typeOnStack.arrayType().isImplicitlyConvertibleTo(targetArrayType) ||
(typeOnStack.arrayType().isByteArray() && targetArrayType.isByteArray()) (typeOnStack.arrayType().isByteArrayOrString() && targetArrayType.isByteArrayOrString())
); );
solAssert( solAssert(
typeOnStack.arrayType().dataStoredIn(DataLocation::CallData) && typeOnStack.arrayType().dataStoredIn(DataLocation::CallData) &&

View File

@ -153,7 +153,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (paramTypes[i]->isDynamicallySized()) if (paramTypes[i]->isDynamicallySized())
{ {
solAssert( solAssert(
dynamic_cast<ArrayType const&>(*paramTypes[i]).isByteArray(), dynamic_cast<ArrayType const&>(*paramTypes[i]).isByteArrayOrString(),
"Expected string or byte array for mapping key type" "Expected string or byte array for mapping key type"
); );
@ -239,7 +239,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (returnTypes[i]->category() == Type::Category::Mapping) if (returnTypes[i]->category() == Type::Category::Mapping)
continue; continue;
if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i])) if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]))
if (!arrayType->isByteArray()) if (!arrayType->isByteArrayOrString())
continue; continue;
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]); pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second); m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second);
@ -1047,7 +1047,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// stack: ArrayReference (newLength-1) // stack: ArrayReference (newLength-1)
ArrayUtils(m_context).accessIndex(*arrayType, false); ArrayUtils(m_context).accessIndex(*arrayType, false);
if (arrayType->isByteArray()) if (arrayType->isByteArrayOrString())
setLValue<StorageByteArrayElement>(_functionCall); setLValue<StorageByteArrayElement>(_functionCall);
else else
setLValueToStorageItem(_functionCall); setLValueToStorageItem(_functionCall);
@ -1084,7 +1084,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
utils().moveToStackTop(1 + type->sizeOnStack()); utils().moveToStackTop(1 + type->sizeOnStack());
utils().moveToStackTop(1 + type->sizeOnStack()); utils().moveToStackTop(1 + type->sizeOnStack());
// stack: argValue storageSlot slotOffset // stack: argValue storageSlot slotOffset
if (!arrayType->isByteArray()) if (!arrayType->isByteArrayOrString())
StorageItem(m_context, *paramType).storeValue(*type, _functionCall.location(), true); StorageItem(m_context, *paramType).storeValue(*type, _functionCall.location(), true);
else else
StorageByteArrayElement(m_context).storeValue(*type, _functionCall.location(), true); StorageByteArrayElement(m_context).storeValue(*type, _functionCall.location(), true);
@ -1165,7 +1165,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// update free memory pointer // update free memory pointer
m_context << Instruction::DUP1; m_context << Instruction::DUP1;
// Stack: memptr requested_length requested_length // Stack: memptr requested_length requested_length
if (arrayType.isByteArray()) if (arrayType.isByteArrayOrString())
// Round up to multiple of 32 // Round up to multiple of 32
m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND; m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND;
else else
@ -2086,7 +2086,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
{ {
case DataLocation::Storage: case DataLocation::Storage:
ArrayUtils(m_context).accessIndex(arrayType); ArrayUtils(m_context).accessIndex(arrayType);
if (arrayType.isByteArray()) if (arrayType.isByteArrayOrString())
{ {
solAssert(!arrayType.isString(), "Index access to string is not allowed."); solAssert(!arrayType.isString(), "Index access to string is not allowed.");
setLValue<StorageByteArrayElement>(_indexAccess); setLValue<StorageByteArrayElement>(_indexAccess);
@ -2096,7 +2096,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
break; break;
case DataLocation::Memory: case DataLocation::Memory:
ArrayUtils(m_context).accessIndex(arrayType); ArrayUtils(m_context).accessIndex(arrayType);
setLValue<MemoryItem>(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArray()); setLValue<MemoryItem>(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArrayOrString());
break; break;
case DataLocation::CallData: case DataLocation::CallData:
ArrayUtils(m_context).accessCallDataArrayElement(arrayType); ArrayUtils(m_context).accessCallDataArrayElement(arrayType);

View File

@ -1183,8 +1183,8 @@ string YulUtilFunctions::arrayLengthFunction(ArrayType const& _type)
w("calldata", _type.location() == DataLocation::CallData); w("calldata", _type.location() == DataLocation::CallData);
if (_type.location() == DataLocation::Storage) if (_type.location() == DataLocation::Storage)
{ {
w("byteArray", _type.isByteArray()); w("byteArray", _type.isByteArrayOrString());
if (_type.isByteArray()) if (_type.isByteArrayOrString())
w("extractByteArrayLength", extractByteArrayLengthFunction()); w("extractByteArrayLength", extractByteArrayLengthFunction());
} }
@ -1220,7 +1220,7 @@ std::string YulUtilFunctions::resizeArrayFunction(ArrayType const& _type)
solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.location() == DataLocation::Storage, "");
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32); solUnimplementedAssert(_type.baseType()->storageBytes() <= 32);
if (_type.isByteArray()) if (_type.isByteArrayOrString())
return resizeDynamicByteArrayFunction(_type); return resizeDynamicByteArrayFunction(_type);
string functionName = "resize_array_" + _type.identifier(); string functionName = "resize_array_" + _type.identifier();
@ -1259,7 +1259,7 @@ string YulUtilFunctions::cleanUpStorageArrayEndFunction(ArrayType const& _type)
{ {
solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.baseType()->category() != Type::Category::Mapping, ""); solAssert(_type.baseType()->category() != Type::Category::Mapping, "");
solAssert(!_type.isByteArray(), ""); solAssert(!_type.isByteArrayOrString(), "");
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32); solUnimplementedAssert(_type.baseType()->storageBytes() <= 32);
string functionName = "cleanup_storage_array_end_" + _type.identifier(); string functionName = "cleanup_storage_array_end_" + _type.identifier();
@ -1319,7 +1319,7 @@ string YulUtilFunctions::resizeDynamicByteArrayFunction(ArrayType const& _type)
string YulUtilFunctions::cleanUpDynamicByteArrayEndSlotsFunction(ArrayType const& _type) string YulUtilFunctions::cleanUpDynamicByteArrayEndSlotsFunction(ArrayType const& _type)
{ {
solAssert(_type.isByteArray(), ""); solAssert(_type.isByteArrayOrString(), "");
solAssert(_type.isDynamicallySized(), ""); solAssert(_type.isDynamicallySized(), "");
string functionName = "clean_up_bytearray_end_slots_" + _type.identifier(); string functionName = "clean_up_bytearray_end_slots_" + _type.identifier();
@ -1479,7 +1479,7 @@ string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type)
solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), ""); solAssert(_type.isDynamicallySized(), "");
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented."); solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented.");
if (_type.isByteArray()) if (_type.isByteArrayOrString())
return storageByteArrayPopFunction(_type); return storageByteArrayPopFunction(_type);
string functionName = "array_pop_" + _type.identifier(); string functionName = "array_pop_" + _type.identifier();
@ -1509,7 +1509,7 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type)
{ {
solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), ""); solAssert(_type.isDynamicallySized(), "");
solAssert(_type.isByteArray(), ""); solAssert(_type.isByteArrayOrString(), "");
string functionName = "byte_array_pop_" + _type.identifier(); string functionName = "byte_array_pop_" + _type.identifier();
return m_functionCollector.createFunction(functionName, [&]() { return m_functionCollector.createFunction(functionName, [&]() {
@ -1566,7 +1566,7 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c
return m_functionCollector.createFunction(functionName, [&]() { return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"( return Whiskers(R"(
function <functionName>(array <values>) { function <functionName>(array <values>) {
<?isByteArray> <?isByteArrayOrString>
let data := sload(array) let data := sload(array)
let oldLen := <extractByteArrayLength>(data) let oldLen := <extractByteArrayLength>(data)
if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() } if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() }
@ -1598,20 +1598,20 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c
let slot, offset := <indexAccess>(array, oldLen) let slot, offset := <indexAccess>(array, oldLen)
<storeValue>(slot, offset <values>) <storeValue>(slot, offset <values>)
} }
<!isByteArray> <!isByteArrayOrString>
let oldLen := sload(array) let oldLen := sload(array)
if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() } if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() }
sstore(array, add(oldLen, 1)) sstore(array, add(oldLen, 1))
let slot, offset := <indexAccess>(array, oldLen) let slot, offset := <indexAccess>(array, oldLen)
<storeValue>(slot, offset <values>) <storeValue>(slot, offset <values>)
</isByteArray> </isByteArrayOrString>
})") })")
("functionName", functionName) ("functionName", functionName)
("values", _fromType->sizeOnStack() == 0 ? "" : ", " + suffixedVariableNameList("value", 0, _fromType->sizeOnStack())) ("values", _fromType->sizeOnStack() == 0 ? "" : ", " + suffixedVariableNameList("value", 0, _fromType->sizeOnStack()))
("panic", panicFunction(PanicCode::ResourceError)) ("panic", panicFunction(PanicCode::ResourceError))
("extractByteArrayLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "") ("extractByteArrayLength", _type.isByteArrayOrString() ? extractByteArrayLengthFunction() : "")
("dataAreaFunction", arrayDataAreaFunction(_type)) ("dataAreaFunction", arrayDataAreaFunction(_type))
("isByteArray", _type.isByteArray()) ("isByteArrayOrString", _type.isByteArrayOrString())
("indexAccess", storageArrayIndexAccessFunction(_type)) ("indexAccess", storageArrayIndexAccessFunction(_type))
("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType())) ("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType()))
("maxArrayLength", (u256(1) << 64).str()) ("maxArrayLength", (u256(1) << 64).str())
@ -1642,9 +1642,9 @@ string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _type)
slot, offset := <indexAccess>(array, oldLen) slot, offset := <indexAccess>(array, oldLen)
})") })")
("functionName", functionName) ("functionName", functionName)
("isBytes", _type.isByteArray()) ("isBytes", _type.isByteArrayOrString())
("increaseBytesSize", _type.isByteArray() ? increaseByteArraySizeFunction(_type) : "") ("increaseBytesSize", _type.isByteArrayOrString() ? increaseByteArraySizeFunction(_type) : "")
("extractLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "") ("extractLength", _type.isByteArrayOrString() ? extractByteArrayLengthFunction() : "")
("panic", panicFunction(PanicCode::ResourceError)) ("panic", panicFunction(PanicCode::ResourceError))
("fetchLength", arrayLengthFunction(_type)) ("fetchLength", arrayLengthFunction(_type))
("indexAccess", storageArrayIndexAccessFunction(_type)) ("indexAccess", storageArrayIndexAccessFunction(_type))
@ -1795,7 +1795,7 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType,
if (!_toType.isDynamicallySized()) if (!_toType.isDynamicallySized())
solAssert(!_fromType.isDynamicallySized() && _fromType.length() <= _toType.length(), ""); solAssert(!_fromType.isDynamicallySized() && _fromType.length() <= _toType.length(), "");
if (_fromType.isByteArray()) if (_fromType.isByteArrayOrString())
return copyByteArrayToStorageFunction(_fromType, _toType); return copyByteArrayToStorageFunction(_fromType, _toType);
if (_fromType.dataStoredIn(DataLocation::Storage) && _toType.baseType()->isValueType()) if (_fromType.dataStoredIn(DataLocation::Storage) && _toType.baseType()->isValueType())
return copyValueArrayStorageToStorageFunction(_fromType, _toType); return copyValueArrayStorageToStorageFunction(_fromType, _toType);
@ -1902,8 +1902,8 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy
*_fromType.copyForLocation(_toType.location(), _toType.isPointer()) == dynamic_cast<ReferenceType const&>(_toType), *_fromType.copyForLocation(_toType.location(), _toType.isPointer()) == dynamic_cast<ReferenceType const&>(_toType),
"" ""
); );
solAssert(_fromType.isByteArray(), ""); solAssert(_fromType.isByteArrayOrString(), "");
solAssert(_toType.isByteArray(), ""); solAssert(_toType.isByteArrayOrString(), "");
string functionName = "copy_byte_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier(); string functionName = "copy_byte_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier();
return m_functionCollector.createFunction(functionName, [&](){ return m_functionCollector.createFunction(functionName, [&](){
@ -1980,8 +1980,8 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const&
solAssert(_toType.baseType()->isValueType(), ""); solAssert(_toType.baseType()->isValueType(), "");
solAssert(_fromType.baseType()->isImplicitlyConvertibleTo(*_toType.baseType()), ""); solAssert(_fromType.baseType()->isImplicitlyConvertibleTo(*_toType.baseType()), "");
solAssert(!_fromType.isByteArray(), ""); solAssert(!_fromType.isByteArrayOrString(), "");
solAssert(!_toType.isByteArray(), ""); solAssert(!_toType.isByteArrayOrString(), "");
solAssert(_fromType.dataStoredIn(DataLocation::Storage), ""); solAssert(_fromType.dataStoredIn(DataLocation::Storage), "");
solAssert(_toType.dataStoredIn(DataLocation::Storage), ""); solAssert(_toType.dataStoredIn(DataLocation::Storage), "");
@ -2155,7 +2155,7 @@ string YulUtilFunctions::arrayConvertLengthToSize(ArrayType const& _type)
})") })")
("functionName", functionName) ("functionName", functionName)
("stride", to_string(_type.location() == DataLocation::Memory ? _type.memoryStride() : _type.calldataStride())) ("stride", to_string(_type.location() == DataLocation::Memory ? _type.memoryStride() : _type.calldataStride()))
("byteArray", _type.isByteArray()) ("byteArray", _type.isByteArrayOrString())
("mul", overflowCheckedIntMulFunction(*TypeProvider::uint256())) ("mul", overflowCheckedIntMulFunction(*TypeProvider::uint256()))
.render(); .render();
default: default:
@ -2187,7 +2187,7 @@ string YulUtilFunctions::arrayAllocationSizeFunction(ArrayType const& _type)
)"); )");
w("functionName", functionName); w("functionName", functionName);
w("panic", panicFunction(PanicCode::ResourceError)); w("panic", panicFunction(PanicCode::ResourceError));
w("byteArray", _type.isByteArray()); w("byteArray", _type.isByteArrayOrString());
w("roundUp", roundUpFunction()); w("roundUp", roundUpFunction());
w("dynamic", _type.isDynamicallySized()); w("dynamic", _type.isDynamicallySized());
return w.render(); return w.render();
@ -2262,7 +2262,7 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type)
("dataAreaFunc", arrayDataAreaFunction(_type)) ("dataAreaFunc", arrayDataAreaFunction(_type))
("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction()) ("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction())
("multipleItemsPerSlot", _type.baseType()->storageBytes() <= 16) ("multipleItemsPerSlot", _type.baseType()->storageBytes() <= 16)
("isBytesArray", _type.isByteArray()) ("isBytesArray", _type.isByteArrayOrString())
("storageSize", _type.baseType()->storageSize().str()) ("storageSize", _type.baseType()->storageSize().str())
("storageBytes", toString(_type.baseType()->storageBytes())) ("storageBytes", toString(_type.baseType()->storageBytes()))
("itemsPerSlot", to_string(32 / _type.baseType()->storageBytes())) ("itemsPerSlot", to_string(32 / _type.baseType()->storageBytes()))
@ -2376,7 +2376,7 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type)
string YulUtilFunctions::nextArrayElementFunction(ArrayType const& _type) string YulUtilFunctions::nextArrayElementFunction(ArrayType const& _type)
{ {
solAssert(!_type.isByteArray(), ""); solAssert(!_type.isByteArrayOrString(), "");
if (_type.dataStoredIn(DataLocation::Storage)) if (_type.dataStoredIn(DataLocation::Storage))
solAssert(_type.baseType()->storageBytes() > 16, ""); solAssert(_type.baseType()->storageBytes() > 16, "");
string functionName = "array_nextElement_" + _type.identifier(); string functionName = "array_nextElement_" + _type.identifier();
@ -2447,7 +2447,7 @@ string YulUtilFunctions::copyArrayFromStorageToMemoryFunction(ArrayType const& _
solAssert(_to.memoryStride() == 32, ""); solAssert(_to.memoryStride() == 32, "");
solAssert(_to.baseType()->dataStoredIn(DataLocation::Memory), ""); solAssert(_to.baseType()->dataStoredIn(DataLocation::Memory), "");
solAssert(_from.baseType()->dataStoredIn(DataLocation::Storage), ""); solAssert(_from.baseType()->dataStoredIn(DataLocation::Storage), "");
solAssert(!_from.isByteArray(), ""); solAssert(!_from.isByteArrayOrString(), "");
solAssert(*_to.withLocation(DataLocation::Storage, _from.isPointer()) == _from, ""); solAssert(*_to.withLocation(DataLocation::Storage, _from.isPointer()) == _from, "");
return Whiskers(R"( return Whiskers(R"(
function <functionName>(slot) -> memPtr { function <functionName>(slot) -> memPtr {
@ -2755,7 +2755,7 @@ string YulUtilFunctions::updateStorageValueFunction(
solAssert(_fromType.category() == Type::Category::StringLiteral, ""); solAssert(_fromType.category() == Type::Category::StringLiteral, "");
solAssert(toReferenceType->category() == Type::Category::Array, ""); solAssert(toReferenceType->category() == Type::Category::Array, "");
auto const& toArrayType = dynamic_cast<ArrayType const&>(*toReferenceType); auto const& toArrayType = dynamic_cast<ArrayType const&>(*toReferenceType);
solAssert(toArrayType.isByteArray(), ""); solAssert(toArrayType.isByteArrayOrString(), "");
return Whiskers(R"( return Whiskers(R"(
function <functionName>(slot<?dynamicOffset>, offset</dynamicOffset>) { function <functionName>(slot<?dynamicOffset>, offset</dynamicOffset>) {
@ -3216,7 +3216,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
auto const& fromType = dynamic_cast<ArraySliceType const&>(_from); auto const& fromType = dynamic_cast<ArraySliceType const&>(_from);
if (_to.category() == Type::Category::FixedBytes) if (_to.category() == Type::Category::FixedBytes)
{ {
solAssert(fromType.arrayType().isByteArray(), "Array types other than bytes not convertible to bytesNN."); solAssert(fromType.arrayType().isByteArrayOrString(), "Array types other than bytes not convertible to bytesNN.");
return bytesToFixedBytesConversionFunction(fromType.arrayType(), dynamic_cast<FixedBytesType const &>(_to)); return bytesToFixedBytesConversionFunction(fromType.arrayType(), dynamic_cast<FixedBytesType const &>(_to));
} }
solAssert(_to.category() == Type::Category::Array); solAssert(_to.category() == Type::Category::Array);
@ -3224,7 +3224,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
solAssert( solAssert(
fromType.arrayType().isImplicitlyConvertibleTo(targetType) || fromType.arrayType().isImplicitlyConvertibleTo(targetType) ||
(fromType.arrayType().isByteArray() && targetType.isByteArray()) (fromType.arrayType().isByteArrayOrString() && targetType.isByteArrayOrString())
); );
solAssert( solAssert(
fromType.arrayType().dataStoredIn(DataLocation::CallData) && fromType.arrayType().dataStoredIn(DataLocation::CallData) &&
@ -3256,7 +3256,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
auto const& fromArrayType = dynamic_cast<ArrayType const&>(_from); auto const& fromArrayType = dynamic_cast<ArrayType const&>(_from);
if (_to.category() == Type::Category::FixedBytes) if (_to.category() == Type::Category::FixedBytes)
{ {
solAssert(fromArrayType.isByteArray(), "Array types other than bytes not convertible to bytesNN."); solAssert(fromArrayType.isByteArrayOrString(), "Array types other than bytes not convertible to bytesNN.");
return bytesToFixedBytesConversionFunction(fromArrayType, dynamic_cast<FixedBytesType const &>(_to)); return bytesToFixedBytesConversionFunction(fromArrayType, dynamic_cast<FixedBytesType const &>(_to));
} }
solAssert(_to.category() == Type::Category::Array, ""); solAssert(_to.category() == Type::Category::Array, "");
@ -3460,7 +3460,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
string YulUtilFunctions::bytesToFixedBytesConversionFunction(ArrayType const& _from, FixedBytesType const& _to) string YulUtilFunctions::bytesToFixedBytesConversionFunction(ArrayType const& _from, FixedBytesType const& _to)
{ {
solAssert(_from.isByteArray() && !_from.isString(), ""); solAssert(_from.isByteArrayOrString() && !_from.isString(), "");
solAssert(_from.isDynamicallySized(), ""); solAssert(_from.isDynamicallySized(), "");
string functionName = "convert_bytes_to_fixedbytes_from_" + _from.identifier() + "_to_" + _to.identifier(); string functionName = "convert_bytes_to_fixedbytes_from_" + _from.identifier() + "_to_" + _to.identifier();
return m_functionCollector.createFunction(functionName, [&](auto& _args, auto& _returnParams) { return m_functionCollector.createFunction(functionName, [&](auto& _args, auto& _returnParams) {
@ -3633,14 +3633,14 @@ string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayTy
{ {
if (_to.dataStoredIn(DataLocation::CallData)) if (_to.dataStoredIn(DataLocation::CallData))
solAssert( solAssert(
_from.dataStoredIn(DataLocation::CallData) && _from.isByteArray() && _to.isByteArray(), _from.dataStoredIn(DataLocation::CallData) && _from.isByteArrayOrString() && _to.isByteArrayOrString(),
"" ""
); );
// 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.
if (_to.location() == DataLocation::Storage) if (_to.location() == DataLocation::Storage)
solAssert( solAssert(
(_to.isPointer() || (_from.isByteArray() && _to.isByteArray())) && (_to.isPointer() || (_from.isByteArrayOrString() && _to.isByteArrayOrString())) &&
_from.location() == DataLocation::Storage, _from.location() == DataLocation::Storage,
"Invalid conversion to storage type." "Invalid conversion to storage type."
); );
@ -4238,7 +4238,7 @@ string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const
} }
else if (_to.category() == Type::Category::Array) else if (_to.category() == Type::Category::Array)
{ {
solAssert(dynamic_cast<ArrayType const&>(_to).isByteArray(), ""); solAssert(dynamic_cast<ArrayType const&>(_to).isByteArrayOrString(), "");
Whiskers templ(R"( Whiskers templ(R"(
function <functionName>() -> converted { function <functionName>() -> converted {
converted := <copyLiteralToMemory>() converted := <copyLiteralToMemory>()

View File

@ -677,7 +677,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
continue; continue;
if ( if (
auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]); auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]);
arrayType && !arrayType->isByteArray() arrayType && !arrayType->isByteArrayOrString()
) )
continue; continue;
@ -698,7 +698,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
solAssert(returnTypes.size() == 1, ""); solAssert(returnTypes.size() == 1, "");
auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes.front()); auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes.front());
if (arrayType) if (arrayType)
solAssert(arrayType->isByteArray(), ""); solAssert(arrayType->isByteArrayOrString(), "");
vector<string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots(); vector<string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots();
returnVariables += retVars; returnVariables += retVars;
code += Whiskers(R"( code += Whiskers(R"(

View File

@ -2088,7 +2088,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
else if (dynamic_cast<UserDefinedValueType const*>(&actualType)) else if (dynamic_cast<UserDefinedValueType const*>(&actualType))
solAssert(member == "wrap" || member == "unwrap"); solAssert(member == "wrap" || member == "unwrap");
else if (auto const* arrayType = dynamic_cast<ArrayType const*>(&actualType)) else if (auto const* arrayType = dynamic_cast<ArrayType const*>(&actualType))
solAssert(arrayType->isByteArray() && member == "concat"); solAssert(arrayType->isByteArrayOrString() && member == "concat");
else else
// The old code generator had a generic "else" case here // The old code generator had a generic "else" case here
// without any specific code being generated, // without any specific code being generated,
@ -2226,7 +2226,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
setLValue(_indexAccess, IRLValue{ setLValue(_indexAccess, IRLValue{
*arrayType.baseType(), *arrayType.baseType(),
IRLValue::Memory{memAddress, arrayType.isByteArray()} IRLValue::Memory{memAddress, arrayType.isByteArrayOrString()}
}); });
break; break;
} }
@ -2240,7 +2240,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
", " + ", " +
expressionAsType(*_indexAccess.indexExpression(), *TypeProvider::uint256()) + expressionAsType(*_indexAccess.indexExpression(), *TypeProvider::uint256()) +
")"; ")";
if (arrayType.isByteArray()) if (arrayType.isByteArrayOrString())
define(_indexAccess) << define(_indexAccess) <<
m_utils.cleanupFunction(*arrayType.baseType()) << m_utils.cleanupFunction(*arrayType.baseType()) <<
"(calldataload(" << "(calldataload(" <<

View File

@ -953,7 +953,7 @@ bool isReturnedFromStructGetter(Type const* _type)
if (category == Type::Category::Mapping) if (category == Type::Category::Mapping)
return false; return false;
if (category == Type::Category::Array) if (category == Type::Category::Array)
return dynamic_cast<ArrayType const&>(*_type).isByteArray(); return dynamic_cast<ArrayType const&>(*_type).isByteArrayOrString();
// default // default
return true; return true;
} }
@ -990,7 +990,7 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
{ {
if ( if (
type->isValueType() || type->isValueType() ||
(type->category() == Type::Category::Array && dynamic_cast<ArrayType const&>(*type).isByteArray()) (type->category() == Type::Category::Array && dynamic_cast<ArrayType const&>(*type).isByteArrayOrString())
) )
{ {
solAssert(symbArguments.empty(), ""); solAssert(symbArguments.empty(), "");
@ -1071,7 +1071,7 @@ void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall)
if (auto sliceType = dynamic_cast<ArraySliceType const*>(argType)) if (auto sliceType = dynamic_cast<ArraySliceType const*>(argType))
arrayType = &sliceType->arrayType(); arrayType = &sliceType->arrayType();
if (arrayType && arrayType->isByteArray() && smt::isFixedBytes(*funCallType)) if (arrayType && arrayType->isByteArrayOrString() && smt::isFixedBytes(*funCallType))
{ {
auto array = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(*argument)); auto array = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(*argument));
bytesToFixedBytesAssertions(*array, _funCall); bytesToFixedBytesAssertions(*array, _funCall);
@ -2695,14 +2695,14 @@ Expression const* SMTEncoder::cleanExpression(Expression const& _expr)
auto typeType = dynamic_cast<TypeType const*>(functionCall->expression().annotation().type); auto typeType = dynamic_cast<TypeType const*>(functionCall->expression().annotation().type);
solAssert(typeType, ""); solAssert(typeType, "");
if (auto const* arrayType = dynamic_cast<ArrayType const*>(typeType->actualType())) if (auto const* arrayType = dynamic_cast<ArrayType const*>(typeType->actualType()))
if (arrayType->isByteArray()) if (arrayType->isByteArrayOrString())
{ {
// this is a cast to `bytes` // this is a cast to `bytes`
solAssert(functionCall->arguments().size() == 1, ""); solAssert(functionCall->arguments().size() == 1, "");
Expression const& arg = *functionCall->arguments()[0]; Expression const& arg = *functionCall->arguments()[0];
if ( if (
auto const* argArrayType = dynamic_cast<ArrayType const*>(arg.annotation().type); auto const* argArrayType = dynamic_cast<ArrayType const*>(arg.annotation().type);
argArrayType && argArrayType->isByteArray() argArrayType && argArrayType->isByteArrayOrString()
) )
return cleanExpression(arg); return cleanExpression(arg);
} }

View File

@ -96,7 +96,7 @@ SortPointer smtSort(frontend::Type const& _type)
auto sliceArrayType = dynamic_cast<ArraySliceType const*>(&_type); auto sliceArrayType = dynamic_cast<ArraySliceType const*>(&_type);
ArrayType const* arrayType = sliceArrayType ? &sliceArrayType->arrayType() : dynamic_cast<ArrayType const*>(&_type); ArrayType const* arrayType = sliceArrayType ? &sliceArrayType->arrayType() : dynamic_cast<ArrayType const*>(&_type);
if ( if (
(arrayType && (arrayType->isString() || arrayType->isByteArray())) || (arrayType && (arrayType->isString() || arrayType->isByteArrayOrString())) ||
_type.category() == frontend::Type::Category::StringLiteral _type.category() == frontend::Type::Category::StringLiteral
) )
tupleName = "bytes"; tupleName = "bytes";

View File

@ -176,7 +176,7 @@ Json::Value ABI::formatType(
ret["type"] = _encodingType.canonicalName() + suffix; ret["type"] = _encodingType.canonicalName() + suffix;
else if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(&_encodingType)) else if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(&_encodingType))
{ {
if (arrayType->isByteArray()) if (arrayType->isByteArrayOrString())
ret["type"] = _encodingType.canonicalName() + suffix; ret["type"] = _encodingType.canonicalName() + suffix;
else else
{ {

View File

@ -94,7 +94,7 @@ void StorageLayout::generate(Type const* _type)
} }
else if (auto arrayType = dynamic_cast<ArrayType const*>(_type)) else if (auto arrayType = dynamic_cast<ArrayType const*>(_type))
{ {
if (arrayType->isByteArray()) if (arrayType->isByteArrayOrString())
typeInfo["encoding"] = "bytes"; typeInfo["encoding"] = "bytes";
else else
{ {