mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
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:
parent
a05d2b356a
commit
9043621747
@ -441,7 +441,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
|
||||
{
|
||||
bool allowed = false;
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(type))
|
||||
allowed = arrayType->isByteArray();
|
||||
allowed = arrayType->isByteArrayOrString();
|
||||
if (!allowed)
|
||||
m_errorReporter.fatalTypeError(9259_error, _variable.location(), "Only constants of value type and byte array type are implemented.");
|
||||
}
|
||||
|
@ -1783,7 +1783,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
|
||||
(
|
||||
(
|
||||
resultArrayType->isPointer() ||
|
||||
(argArrayType->isByteArray() && resultArrayType->isByteArray())
|
||||
(argArrayType->isByteArrayOrString() && resultArrayType->isByteArrayOrString())
|
||||
) &&
|
||||
resultArrayType->location() == DataLocation::Storage
|
||||
),
|
||||
@ -1791,7 +1791,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
|
||||
);
|
||||
else
|
||||
solAssert(
|
||||
argArrayType->isByteArray() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes,
|
||||
argArrayType->isByteArrayOrString() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes,
|
||||
""
|
||||
);
|
||||
}
|
||||
|
@ -1206,7 +1206,7 @@ BoolResult StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo)
|
||||
);
|
||||
return
|
||||
arrayType->location() != DataLocation::CallData &&
|
||||
arrayType->isByteArray() &&
|
||||
arrayType->isByteArrayOrString() &&
|
||||
!(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer());
|
||||
}
|
||||
else
|
||||
@ -1530,7 +1530,7 @@ BoolResult ArrayType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
||||
if (_convertTo.category() != category())
|
||||
return false;
|
||||
auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
|
||||
if (convertTo.isByteArray() != isByteArray() || convertTo.isString() != isString())
|
||||
if (convertTo.isByteArrayOrString() != isByteArrayOrString() || convertTo.isString() != isString())
|
||||
return false;
|
||||
// memory/calldata to storage can be converted, but only to a direct storage reference
|
||||
if (convertTo.location() == DataLocation::Storage && location() != DataLocation::Storage && convertTo.isPointer())
|
||||
@ -1571,11 +1571,11 @@ BoolResult ArrayType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||
return true;
|
||||
// allow conversion bytes <-> string and bytes -> bytesNN
|
||||
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);
|
||||
if (convertTo.location() != location())
|
||||
return false;
|
||||
if (!isByteArray() || !convertTo.isByteArray())
|
||||
if (!isByteArrayOrString() || !convertTo.isByteArrayOrString())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -1585,7 +1585,7 @@ string ArrayType::richIdentifier() const
|
||||
string id;
|
||||
if (isString())
|
||||
id = "t_string";
|
||||
else if (isByteArray())
|
||||
else if (isByteArrayOrString())
|
||||
id = "t_bytes";
|
||||
else
|
||||
{
|
||||
@ -1608,7 +1608,7 @@ bool ArrayType::operator==(Type const& _other) const
|
||||
ArrayType const& other = dynamic_cast<ArrayType const&>(_other);
|
||||
if (
|
||||
!ReferenceType::operator==(other) ||
|
||||
other.isByteArray() != isByteArray() ||
|
||||
other.isByteArrayOrString() != isByteArrayOrString() ||
|
||||
other.isString() != isString() ||
|
||||
other.isDynamicallySized() != isDynamicallySized()
|
||||
)
|
||||
@ -1751,7 +1751,7 @@ string ArrayType::toString(bool _short) const
|
||||
string ret;
|
||||
if (isString())
|
||||
ret = "string";
|
||||
else if (isByteArray())
|
||||
else if (isByteArrayOrString())
|
||||
ret = "bytes";
|
||||
else
|
||||
{
|
||||
@ -1770,7 +1770,7 @@ string ArrayType::canonicalName() const
|
||||
string ret;
|
||||
if (isString())
|
||||
ret = "string";
|
||||
else if (isByteArray())
|
||||
else if (isByteArrayOrString())
|
||||
ret = "bytes";
|
||||
else
|
||||
{
|
||||
@ -1784,7 +1784,7 @@ string ArrayType::canonicalName() const
|
||||
|
||||
string ArrayType::signatureInExternalFunction(bool _structsByName) const
|
||||
{
|
||||
if (isByteArray())
|
||||
if (isByteArrayOrString())
|
||||
return canonicalName();
|
||||
else
|
||||
{
|
||||
@ -1899,7 +1899,7 @@ u256 ArrayType::memoryDataSize() const
|
||||
{
|
||||
solAssert(!isDynamicallySized(), "");
|
||||
solAssert(m_location == DataLocation::Memory, "");
|
||||
solAssert(!isByteArray(), "");
|
||||
solAssert(!isByteArrayOrString(), "");
|
||||
bigint size = bigint(m_length) * m_baseType->memoryHeadSize();
|
||||
solAssert(size <= numeric_limits<u256>::max(), "Array size does not fit u256.");
|
||||
return u256(size);
|
||||
@ -2701,7 +2701,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
|
||||
}
|
||||
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
|
||||
{
|
||||
if (arrayType->isByteArray())
|
||||
if (arrayType->isByteArrayOrString())
|
||||
// Return byte arrays as whole.
|
||||
break;
|
||||
returnType = arrayType->baseType();
|
||||
@ -2720,7 +2720,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
|
||||
if (member.type->category() != Category::Mapping)
|
||||
{
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(member.type))
|
||||
if (!arrayType->isByteArray())
|
||||
if (!arrayType->isByteArrayOrString())
|
||||
continue;
|
||||
m_returnParameterTypes.push_back(TypeProvider::withLocationIfReference(
|
||||
DataLocation::Memory,
|
||||
@ -3813,7 +3813,7 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
|
||||
}
|
||||
else if (
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(m_actualType);
|
||||
arrayType && arrayType->isByteArray()
|
||||
arrayType && arrayType->isByteArrayOrString()
|
||||
)
|
||||
members.emplace_back("concat", TypeProvider::function(
|
||||
TypePointers{},
|
||||
|
@ -838,7 +838,7 @@ public:
|
||||
BoolResult validForLocation(DataLocation _loc) const override;
|
||||
|
||||
/// @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
|
||||
bool isString() const { return m_arrayKind == ArrayKind::String; }
|
||||
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;
|
||||
|
||||
/// 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.
|
||||
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.
|
||||
unsigned storageStride() const { return isByteArray() ? 1 : m_baseType->storageBytes(); }
|
||||
unsigned storageStride() const { return isByteArrayOrString() ? 1 : m_baseType->storageBytes(); }
|
||||
|
||||
void clearCache() const override;
|
||||
|
||||
|
@ -312,7 +312,7 @@ string ABIFunctions::abiEncodingFunction(
|
||||
{
|
||||
case DataLocation::CallData:
|
||||
if (
|
||||
fromArray->isByteArray() ||
|
||||
fromArray->isByteArrayOrString() ||
|
||||
*fromArray->baseType() == *TypeProvider::uint256() ||
|
||||
*fromArray->baseType() == FixedBytesType(32)
|
||||
)
|
||||
@ -320,7 +320,7 @@ string ABIFunctions::abiEncodingFunction(
|
||||
else
|
||||
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
|
||||
case DataLocation::Memory:
|
||||
if (fromArray->isByteArray())
|
||||
if (fromArray->isByteArrayOrString())
|
||||
return abiEncodingFunctionMemoryByteArray(*fromArray, *toArray, _options);
|
||||
else
|
||||
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
|
||||
@ -448,7 +448,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
|
||||
solAssert(fromArrayType.location() == DataLocation::CallData, "");
|
||||
solAssert(
|
||||
fromArrayType.isByteArray() ||
|
||||
fromArrayType.isByteArrayOrString() ||
|
||||
*fromArrayType.baseType() == *TypeProvider::uint256() ||
|
||||
*fromArrayType.baseType() == FixedBytesType(32),
|
||||
""
|
||||
@ -468,7 +468,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
_to.identifier() +
|
||||
_options.toFunctionNameSuffix();
|
||||
return createFunction(functionName, [&]() {
|
||||
bool needsPadding = _options.padded && fromArrayType.isByteArray();
|
||||
bool needsPadding = _options.padded && fromArrayType.isByteArrayOrString();
|
||||
if (fromArrayType.isDynamicallySized())
|
||||
{
|
||||
Whiskers templ(R"(
|
||||
@ -482,7 +482,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
)");
|
||||
templ("storeLength", arrayStoreLengthForEncodingFunction(toArrayType, _options));
|
||||
templ("functionName", functionName);
|
||||
if (fromArrayType.isByteArray() || fromArrayType.calldataStride() == 1)
|
||||
if (fromArrayType.isByteArrayOrString() || fromArrayType.calldataStride() == 1)
|
||||
templ("scaleLengthByStride", "");
|
||||
else
|
||||
templ("scaleLengthByStride",
|
||||
@ -536,7 +536,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
|
||||
|
||||
solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), "");
|
||||
solAssert(_from.length() == _to.length(), "");
|
||||
solAssert(!_from.isByteArray(), "");
|
||||
solAssert(!_from.isByteArrayOrString(), "");
|
||||
if (_from.dataStoredIn(DataLocation::Storage))
|
||||
solAssert(_from.baseType()->storageBytes() > 16, "");
|
||||
|
||||
@ -647,10 +647,10 @@ string ABIFunctions::abiEncodingFunctionMemoryByteArray(
|
||||
solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), "");
|
||||
solAssert(_from.length() == _to.length(), "");
|
||||
solAssert(_from.dataStoredIn(DataLocation::Memory), "");
|
||||
solAssert(_from.isByteArray(), "");
|
||||
solAssert(_from.isByteArrayOrString(), "");
|
||||
|
||||
return createFunction(functionName, [&]() {
|
||||
solAssert(_to.isByteArray(), "");
|
||||
solAssert(_to.isByteArrayOrString(), "");
|
||||
Whiskers templ(R"(
|
||||
function <functionName>(value, pos) -> end {
|
||||
let length := <lengthFun>(value)
|
||||
@ -686,9 +686,9 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
||||
solAssert(_from.dataStoredIn(DataLocation::Storage), "");
|
||||
|
||||
return createFunction(functionName, [&]() {
|
||||
if (_from.isByteArray())
|
||||
if (_from.isByteArrayOrString())
|
||||
{
|
||||
solAssert(_to.isByteArray(), "");
|
||||
solAssert(_to.isByteArrayOrString(), "");
|
||||
Whiskers templ(R"(
|
||||
// <readableTypeNameFrom> -> <readableTypeNameTo>
|
||||
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)
|
||||
{
|
||||
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
|
||||
if (_type.isByteArray())
|
||||
if (_type.isByteArrayOrString())
|
||||
return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory);
|
||||
solAssert(_type.calldataStride() > 0, "");
|
||||
|
||||
@ -1275,7 +1275,7 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
|
||||
string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
|
||||
{
|
||||
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
|
||||
solAssert(_type.isByteArray(), "");
|
||||
solAssert(_type.isByteArrayOrString(), "");
|
||||
|
||||
string functionName =
|
||||
"abi_decode_available_length_" +
|
||||
|
@ -50,8 +50,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
||||
solAssert(_targetType.location() == DataLocation::Storage, "");
|
||||
|
||||
Type const* uint256 = TypeProvider::uint256();
|
||||
Type const* targetBaseType = _targetType.isByteArray() ? uint256 : _targetType.baseType();
|
||||
Type const* sourceBaseType = _sourceType.isByteArray() ? uint256 : _sourceType.baseType();
|
||||
Type const* targetBaseType = _targetType.isByteArrayOrString() ? uint256 : _targetType.baseType();
|
||||
Type const* sourceBaseType = _sourceType.isByteArrayOrString() ? uint256 : _sourceType.baseType();
|
||||
|
||||
// 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
|
||||
if (_targetType.isDynamicallySized())
|
||||
// store new target length
|
||||
if (!_targetType.isByteArray())
|
||||
if (!_targetType.isByteArrayOrString())
|
||||
// Otherwise, length will be stored below.
|
||||
_context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE;
|
||||
if (sourceBaseType->category() == Type::Category::Mapping)
|
||||
@ -126,7 +126,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
||||
evmasm::AssemblyItem copyLoopEndWithoutByteOffset = _context.newTag();
|
||||
|
||||
// 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
|
||||
_context << Instruction::DUP3;
|
||||
@ -141,7 +141,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
||||
_context << Instruction::DUP3 << u256(31) << Instruction::LT;
|
||||
evmasm::AssemblyItem longByteArray = _context.appendConditionalJump();
|
||||
// store the short byte array
|
||||
solAssert(_sourceType.isByteArray(), "");
|
||||
solAssert(_sourceType.isByteArrayOrString(), "");
|
||||
if (_sourceType.location() == DataLocation::Storage)
|
||||
{
|
||||
// just copy the slot, it contains length and data
|
||||
@ -323,7 +323,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
|
||||
{
|
||||
if (!_sourceType.isDynamicallySized())
|
||||
m_context << _sourceType.length();
|
||||
if (!_sourceType.isByteArray())
|
||||
if (!_sourceType.isByteArrayOrString())
|
||||
convertLengthToSize(_sourceType);
|
||||
|
||||
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;
|
||||
}
|
||||
if (!_sourceType.isByteArray())
|
||||
if (!_sourceType.isByteArrayOrString())
|
||||
convertLengthToSize(_sourceType);
|
||||
// stack: <target> <source> <size>
|
||||
m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::DUP4;
|
||||
// We can resort to copying full 32 bytes only if
|
||||
// - the length is known to be a multiple of 32 or
|
||||
// - we will pad to full 32 bytes later anyway.
|
||||
if (!_sourceType.isByteArray() || _padToWordBoundaries)
|
||||
if (!_sourceType.isByteArrayOrString() || _padToWordBoundaries)
|
||||
utils.memoryCopy32();
|
||||
else
|
||||
utils.memoryCopy();
|
||||
@ -390,7 +390,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
|
||||
m_context << Instruction::SWAP1 << Instruction::POP;
|
||||
// stack: <target> <size>
|
||||
|
||||
bool paddingNeeded = _padToWordBoundaries && _sourceType.isByteArray();
|
||||
bool paddingNeeded = _padToWordBoundaries && _sourceType.isByteArrayOrString();
|
||||
|
||||
if (paddingNeeded)
|
||||
{
|
||||
@ -446,7 +446,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
|
||||
m_context << Instruction::DUP1 << Instruction::ISZERO;
|
||||
evmasm::AssemblyItem loopEnd = m_context.appendConditionalJump();
|
||||
// Special case for tightly-stored byte arrays
|
||||
if (_sourceType.isByteArray())
|
||||
if (_sourceType.isByteArrayOrString())
|
||||
{
|
||||
// stack here: memory_offset storage_offset length
|
||||
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
|
||||
bool haveByteOffset = !_sourceType.isByteArray() && storageBytes <= 16;
|
||||
bool haveByteOffset = !_sourceType.isByteArrayOrString() && storageBytes <= 16;
|
||||
if (haveByteOffset)
|
||||
m_context << u256(0) << Instruction::SWAP1;
|
||||
// stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset
|
||||
evmasm::AssemblyItem loopStart = m_context.newTag();
|
||||
m_context << loopStart;
|
||||
// load and store
|
||||
if (_sourceType.isByteArray())
|
||||
if (_sourceType.isByteArrayOrString())
|
||||
{
|
||||
// Packed both in storage and memory.
|
||||
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
|
||||
if (haveByteOffset)
|
||||
m_context << Instruction::SWAP1 << Instruction::POP;
|
||||
if (!_sourceType.isByteArray())
|
||||
if (!_sourceType.isByteArrayOrString())
|
||||
{
|
||||
solAssert(_sourceType.calldataStride() % 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_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;
|
||||
// Special case: short byte arrays are stored togeher with their length
|
||||
evmasm::AssemblyItem endTag = m_context.newTag();
|
||||
if (_type.isByteArray())
|
||||
if (_type.isByteArrayOrString())
|
||||
{
|
||||
// stack: ref old_length
|
||||
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);
|
||||
solAssert(_type.location() == DataLocation::Storage, "");
|
||||
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.");
|
||||
|
||||
unsigned stackHeightStart = _context.stackHeight();
|
||||
@ -677,7 +677,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
|
||||
solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "2");
|
||||
|
||||
// Special case for short byte arrays, they are stored together with their length
|
||||
if (_type.isByteArray())
|
||||
if (_type.isByteArrayOrString())
|
||||
{
|
||||
evmasm::AssemblyItem regularPath = _context.newTag();
|
||||
// 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
|
||||
// store new length
|
||||
_context << Instruction::DUP2;
|
||||
if (_type.isByteArray())
|
||||
if (_type.isByteArrayOrString())
|
||||
// For a "long" byte array, store length as 2*length+1
|
||||
_context << Instruction::DUP1 << Instruction::ADD << u256(1) << Instruction::ADD;
|
||||
_context << Instruction::DUP4 << Instruction::SSTORE;
|
||||
@ -806,10 +806,10 @@ void ArrayUtils::incrementDynamicArraySize(ArrayType const& _type) const
|
||||
{
|
||||
solAssert(_type.location() == DataLocation::Storage, "");
|
||||
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.");
|
||||
|
||||
if (_type.isByteArray())
|
||||
if (_type.isByteArrayOrString())
|
||||
{
|
||||
// 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
|
||||
@ -850,10 +850,10 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
||||
{
|
||||
solAssert(_type.location() == DataLocation::Storage, "");
|
||||
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.");
|
||||
|
||||
if (_type.isByteArray())
|
||||
if (_type.isByteArrayOrString())
|
||||
{
|
||||
m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::DUP1;
|
||||
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
|
||||
@ -999,7 +999,7 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_arrayType.isByteArray())
|
||||
if (!_arrayType.isByteArrayOrString())
|
||||
{
|
||||
if (_arrayType.location() == DataLocation::Memory)
|
||||
m_context << _arrayType.memoryStride();
|
||||
@ -1031,7 +1031,7 @@ void ArrayUtils::retrieveLength(ArrayType const& _arrayType, unsigned _stackDept
|
||||
break;
|
||||
case DataLocation::Storage:
|
||||
m_context << Instruction::SLOAD;
|
||||
if (_arrayType.isByteArray())
|
||||
if (_arrayType.isByteArrayOrString())
|
||||
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
|
||||
break;
|
||||
}
|
||||
@ -1062,7 +1062,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
|
||||
{
|
||||
case DataLocation::Memory:
|
||||
// stack: <base_ref> <index>
|
||||
if (!_arrayType.isByteArray())
|
||||
if (!_arrayType.isByteArrayOrString())
|
||||
m_context << u256(_arrayType.memoryHeadSize()) << Instruction::MUL;
|
||||
if (_arrayType.isDynamicallySized())
|
||||
m_context << u256(32) << Instruction::ADD;
|
||||
@ -1071,7 +1071,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
|
||||
m_context << Instruction::ADD;
|
||||
break;
|
||||
case DataLocation::CallData:
|
||||
if (!_arrayType.isByteArray())
|
||||
if (!_arrayType.isByteArrayOrString())
|
||||
{
|
||||
m_context << _arrayType.calldataStride();
|
||||
m_context << Instruction::MUL;
|
||||
@ -1090,7 +1090,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
|
||||
// stack: [<base_ref>] <index> <base_ref>
|
||||
|
||||
evmasm::AssemblyItem endTag = m_context.newTag();
|
||||
if (_arrayType.isByteArray())
|
||||
if (_arrayType.isByteArrayOrString())
|
||||
{
|
||||
// Special case of short byte arrays.
|
||||
m_context << Instruction::SWAP1;
|
||||
@ -1153,7 +1153,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d
|
||||
{
|
||||
solAssert(_arrayType.baseType()->storageBytes() <= 32, "");
|
||||
if (
|
||||
!_arrayType.isByteArray() &&
|
||||
!_arrayType.isByteArrayOrString() &&
|
||||
_arrayType.baseType()->storageBytes() < 32 &&
|
||||
m_context.useABICoderV2()
|
||||
)
|
||||
@ -1165,7 +1165,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d
|
||||
CompilerUtils(m_context).loadFromMemoryDynamic(
|
||||
*_arrayType.baseType(),
|
||||
true,
|
||||
!_arrayType.isByteArray(),
|
||||
!_arrayType.isByteArrayOrString(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
@ -970,7 +970,7 @@ void CompilerUtils::convertType(
|
||||
else if (targetTypeCategory == Type::Category::Array)
|
||||
{
|
||||
auto const& arrayType = dynamic_cast<ArrayType const&>(_targetType);
|
||||
solAssert(arrayType.isByteArray());
|
||||
solAssert(arrayType.isByteArrayOrString());
|
||||
size_t storageSize = 32 + ((data.size() + 31) / 32) * 32;
|
||||
allocateMemory(storageSize);
|
||||
// stack: mempos
|
||||
@ -992,7 +992,7 @@ void CompilerUtils::convertType(
|
||||
if (_targetType.category() == Type::Category::FixedBytes)
|
||||
{
|
||||
solAssert(
|
||||
typeOnStack.isByteArray() && !typeOnStack.isString(),
|
||||
typeOnStack.isByteArrayOrString() && !typeOnStack.isString(),
|
||||
"Array types other than bytes not convertible to bytesNN."
|
||||
);
|
||||
solAssert(typeOnStack.isDynamicallySized());
|
||||
@ -1019,7 +1019,7 @@ void CompilerUtils::convertType(
|
||||
case DataLocation::Storage:
|
||||
// Other cases are done explicitly in LValue::storeValue, and only possible by assignment.
|
||||
solAssert(
|
||||
(targetType.isPointer() || (typeOnStack.isByteArray() && targetType.isByteArray())) &&
|
||||
(targetType.isPointer() || (typeOnStack.isByteArrayOrString() && targetType.isByteArrayOrString())) &&
|
||||
typeOnStack.location() == DataLocation::Storage,
|
||||
"Invalid conversion to storage type."
|
||||
);
|
||||
@ -1105,7 +1105,7 @@ void CompilerUtils::convertType(
|
||||
}
|
||||
case DataLocation::CallData:
|
||||
solAssert(
|
||||
((targetType.isByteArray() && typeOnStack.isByteArray()) || _typeOnStack == _targetType) &&
|
||||
((targetType.isByteArrayOrString() && typeOnStack.isByteArrayOrString()) || _typeOnStack == _targetType) &&
|
||||
typeOnStack.location() == DataLocation::CallData,
|
||||
"Invalid conversion to calldata type."
|
||||
);
|
||||
@ -1119,7 +1119,7 @@ void CompilerUtils::convertType(
|
||||
if (_targetType.category() == Type::Category::FixedBytes)
|
||||
{
|
||||
solAssert(
|
||||
typeOnStack.arrayType().isByteArray() && !typeOnStack.arrayType().isString(),
|
||||
typeOnStack.arrayType().isByteArrayOrString() && !typeOnStack.arrayType().isString(),
|
||||
"Array types other than bytes not convertible to bytesNN."
|
||||
);
|
||||
solAssert(typeOnStack.isDynamicallySized());
|
||||
@ -1142,7 +1142,7 @@ void CompilerUtils::convertType(
|
||||
auto const& targetArrayType = dynamic_cast<ArrayType const&>(_targetType);
|
||||
solAssert(
|
||||
typeOnStack.arrayType().isImplicitlyConvertibleTo(targetArrayType) ||
|
||||
(typeOnStack.arrayType().isByteArray() && targetArrayType.isByteArray())
|
||||
(typeOnStack.arrayType().isByteArrayOrString() && targetArrayType.isByteArrayOrString())
|
||||
);
|
||||
solAssert(
|
||||
typeOnStack.arrayType().dataStoredIn(DataLocation::CallData) &&
|
||||
|
@ -153,7 +153,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
||||
if (paramTypes[i]->isDynamicallySized())
|
||||
{
|
||||
solAssert(
|
||||
dynamic_cast<ArrayType const&>(*paramTypes[i]).isByteArray(),
|
||||
dynamic_cast<ArrayType const&>(*paramTypes[i]).isByteArrayOrString(),
|
||||
"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)
|
||||
continue;
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]))
|
||||
if (!arrayType->isByteArray())
|
||||
if (!arrayType->isByteArrayOrString())
|
||||
continue;
|
||||
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
|
||||
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)
|
||||
ArrayUtils(m_context).accessIndex(*arrayType, false);
|
||||
|
||||
if (arrayType->isByteArray())
|
||||
if (arrayType->isByteArrayOrString())
|
||||
setLValue<StorageByteArrayElement>(_functionCall);
|
||||
else
|
||||
setLValueToStorageItem(_functionCall);
|
||||
@ -1084,7 +1084,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
utils().moveToStackTop(1 + type->sizeOnStack());
|
||||
utils().moveToStackTop(1 + type->sizeOnStack());
|
||||
// stack: argValue storageSlot slotOffset
|
||||
if (!arrayType->isByteArray())
|
||||
if (!arrayType->isByteArrayOrString())
|
||||
StorageItem(m_context, *paramType).storeValue(*type, _functionCall.location(), true);
|
||||
else
|
||||
StorageByteArrayElement(m_context).storeValue(*type, _functionCall.location(), true);
|
||||
@ -1165,7 +1165,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
// update free memory pointer
|
||||
m_context << Instruction::DUP1;
|
||||
// Stack: memptr requested_length requested_length
|
||||
if (arrayType.isByteArray())
|
||||
if (arrayType.isByteArrayOrString())
|
||||
// Round up to multiple of 32
|
||||
m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND;
|
||||
else
|
||||
@ -2086,7 +2086,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||
{
|
||||
case DataLocation::Storage:
|
||||
ArrayUtils(m_context).accessIndex(arrayType);
|
||||
if (arrayType.isByteArray())
|
||||
if (arrayType.isByteArrayOrString())
|
||||
{
|
||||
solAssert(!arrayType.isString(), "Index access to string is not allowed.");
|
||||
setLValue<StorageByteArrayElement>(_indexAccess);
|
||||
@ -2096,7 +2096,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||
break;
|
||||
case DataLocation::Memory:
|
||||
ArrayUtils(m_context).accessIndex(arrayType);
|
||||
setLValue<MemoryItem>(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArray());
|
||||
setLValue<MemoryItem>(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArrayOrString());
|
||||
break;
|
||||
case DataLocation::CallData:
|
||||
ArrayUtils(m_context).accessCallDataArrayElement(arrayType);
|
||||
|
@ -1183,8 +1183,8 @@ string YulUtilFunctions::arrayLengthFunction(ArrayType const& _type)
|
||||
w("calldata", _type.location() == DataLocation::CallData);
|
||||
if (_type.location() == DataLocation::Storage)
|
||||
{
|
||||
w("byteArray", _type.isByteArray());
|
||||
if (_type.isByteArray())
|
||||
w("byteArray", _type.isByteArrayOrString());
|
||||
if (_type.isByteArrayOrString())
|
||||
w("extractByteArrayLength", extractByteArrayLengthFunction());
|
||||
}
|
||||
|
||||
@ -1220,7 +1220,7 @@ std::string YulUtilFunctions::resizeArrayFunction(ArrayType const& _type)
|
||||
solAssert(_type.location() == DataLocation::Storage, "");
|
||||
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32);
|
||||
|
||||
if (_type.isByteArray())
|
||||
if (_type.isByteArrayOrString())
|
||||
return resizeDynamicByteArrayFunction(_type);
|
||||
|
||||
string functionName = "resize_array_" + _type.identifier();
|
||||
@ -1259,7 +1259,7 @@ string YulUtilFunctions::cleanUpStorageArrayEndFunction(ArrayType const& _type)
|
||||
{
|
||||
solAssert(_type.location() == DataLocation::Storage, "");
|
||||
solAssert(_type.baseType()->category() != Type::Category::Mapping, "");
|
||||
solAssert(!_type.isByteArray(), "");
|
||||
solAssert(!_type.isByteArrayOrString(), "");
|
||||
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32);
|
||||
|
||||
string functionName = "cleanup_storage_array_end_" + _type.identifier();
|
||||
@ -1319,7 +1319,7 @@ string YulUtilFunctions::resizeDynamicByteArrayFunction(ArrayType const& _type)
|
||||
|
||||
string YulUtilFunctions::cleanUpDynamicByteArrayEndSlotsFunction(ArrayType const& _type)
|
||||
{
|
||||
solAssert(_type.isByteArray(), "");
|
||||
solAssert(_type.isByteArrayOrString(), "");
|
||||
solAssert(_type.isDynamicallySized(), "");
|
||||
|
||||
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.isDynamicallySized(), "");
|
||||
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented.");
|
||||
if (_type.isByteArray())
|
||||
if (_type.isByteArrayOrString())
|
||||
return storageByteArrayPopFunction(_type);
|
||||
|
||||
string functionName = "array_pop_" + _type.identifier();
|
||||
@ -1509,7 +1509,7 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type)
|
||||
{
|
||||
solAssert(_type.location() == DataLocation::Storage, "");
|
||||
solAssert(_type.isDynamicallySized(), "");
|
||||
solAssert(_type.isByteArray(), "");
|
||||
solAssert(_type.isByteArrayOrString(), "");
|
||||
|
||||
string functionName = "byte_array_pop_" + _type.identifier();
|
||||
return m_functionCollector.createFunction(functionName, [&]() {
|
||||
@ -1566,7 +1566,7 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c
|
||||
return m_functionCollector.createFunction(functionName, [&]() {
|
||||
return Whiskers(R"(
|
||||
function <functionName>(array <values>) {
|
||||
<?isByteArray>
|
||||
<?isByteArrayOrString>
|
||||
let data := sload(array)
|
||||
let oldLen := <extractByteArrayLength>(data)
|
||||
if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() }
|
||||
@ -1598,20 +1598,20 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c
|
||||
let slot, offset := <indexAccess>(array, oldLen)
|
||||
<storeValue>(slot, offset <values>)
|
||||
}
|
||||
<!isByteArray>
|
||||
<!isByteArrayOrString>
|
||||
let oldLen := sload(array)
|
||||
if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() }
|
||||
sstore(array, add(oldLen, 1))
|
||||
let slot, offset := <indexAccess>(array, oldLen)
|
||||
<storeValue>(slot, offset <values>)
|
||||
</isByteArray>
|
||||
</isByteArrayOrString>
|
||||
})")
|
||||
("functionName", functionName)
|
||||
("values", _fromType->sizeOnStack() == 0 ? "" : ", " + suffixedVariableNameList("value", 0, _fromType->sizeOnStack()))
|
||||
("panic", panicFunction(PanicCode::ResourceError))
|
||||
("extractByteArrayLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "")
|
||||
("extractByteArrayLength", _type.isByteArrayOrString() ? extractByteArrayLengthFunction() : "")
|
||||
("dataAreaFunction", arrayDataAreaFunction(_type))
|
||||
("isByteArray", _type.isByteArray())
|
||||
("isByteArrayOrString", _type.isByteArrayOrString())
|
||||
("indexAccess", storageArrayIndexAccessFunction(_type))
|
||||
("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType()))
|
||||
("maxArrayLength", (u256(1) << 64).str())
|
||||
@ -1642,9 +1642,9 @@ string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _type)
|
||||
slot, offset := <indexAccess>(array, oldLen)
|
||||
})")
|
||||
("functionName", functionName)
|
||||
("isBytes", _type.isByteArray())
|
||||
("increaseBytesSize", _type.isByteArray() ? increaseByteArraySizeFunction(_type) : "")
|
||||
("extractLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "")
|
||||
("isBytes", _type.isByteArrayOrString())
|
||||
("increaseBytesSize", _type.isByteArrayOrString() ? increaseByteArraySizeFunction(_type) : "")
|
||||
("extractLength", _type.isByteArrayOrString() ? extractByteArrayLengthFunction() : "")
|
||||
("panic", panicFunction(PanicCode::ResourceError))
|
||||
("fetchLength", arrayLengthFunction(_type))
|
||||
("indexAccess", storageArrayIndexAccessFunction(_type))
|
||||
@ -1795,7 +1795,7 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType,
|
||||
if (!_toType.isDynamicallySized())
|
||||
solAssert(!_fromType.isDynamicallySized() && _fromType.length() <= _toType.length(), "");
|
||||
|
||||
if (_fromType.isByteArray())
|
||||
if (_fromType.isByteArrayOrString())
|
||||
return copyByteArrayToStorageFunction(_fromType, _toType);
|
||||
if (_fromType.dataStoredIn(DataLocation::Storage) && _toType.baseType()->isValueType())
|
||||
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),
|
||||
""
|
||||
);
|
||||
solAssert(_fromType.isByteArray(), "");
|
||||
solAssert(_toType.isByteArray(), "");
|
||||
solAssert(_fromType.isByteArrayOrString(), "");
|
||||
solAssert(_toType.isByteArrayOrString(), "");
|
||||
|
||||
string functionName = "copy_byte_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier();
|
||||
return m_functionCollector.createFunction(functionName, [&](){
|
||||
@ -1980,8 +1980,8 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const&
|
||||
solAssert(_toType.baseType()->isValueType(), "");
|
||||
solAssert(_fromType.baseType()->isImplicitlyConvertibleTo(*_toType.baseType()), "");
|
||||
|
||||
solAssert(!_fromType.isByteArray(), "");
|
||||
solAssert(!_toType.isByteArray(), "");
|
||||
solAssert(!_fromType.isByteArrayOrString(), "");
|
||||
solAssert(!_toType.isByteArrayOrString(), "");
|
||||
solAssert(_fromType.dataStoredIn(DataLocation::Storage), "");
|
||||
solAssert(_toType.dataStoredIn(DataLocation::Storage), "");
|
||||
|
||||
@ -2155,7 +2155,7 @@ string YulUtilFunctions::arrayConvertLengthToSize(ArrayType const& _type)
|
||||
})")
|
||||
("functionName", functionName)
|
||||
("stride", to_string(_type.location() == DataLocation::Memory ? _type.memoryStride() : _type.calldataStride()))
|
||||
("byteArray", _type.isByteArray())
|
||||
("byteArray", _type.isByteArrayOrString())
|
||||
("mul", overflowCheckedIntMulFunction(*TypeProvider::uint256()))
|
||||
.render();
|
||||
default:
|
||||
@ -2187,7 +2187,7 @@ string YulUtilFunctions::arrayAllocationSizeFunction(ArrayType const& _type)
|
||||
)");
|
||||
w("functionName", functionName);
|
||||
w("panic", panicFunction(PanicCode::ResourceError));
|
||||
w("byteArray", _type.isByteArray());
|
||||
w("byteArray", _type.isByteArrayOrString());
|
||||
w("roundUp", roundUpFunction());
|
||||
w("dynamic", _type.isDynamicallySized());
|
||||
return w.render();
|
||||
@ -2262,7 +2262,7 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type)
|
||||
("dataAreaFunc", arrayDataAreaFunction(_type))
|
||||
("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction())
|
||||
("multipleItemsPerSlot", _type.baseType()->storageBytes() <= 16)
|
||||
("isBytesArray", _type.isByteArray())
|
||||
("isBytesArray", _type.isByteArrayOrString())
|
||||
("storageSize", _type.baseType()->storageSize().str())
|
||||
("storageBytes", toString(_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)
|
||||
{
|
||||
solAssert(!_type.isByteArray(), "");
|
||||
solAssert(!_type.isByteArrayOrString(), "");
|
||||
if (_type.dataStoredIn(DataLocation::Storage))
|
||||
solAssert(_type.baseType()->storageBytes() > 16, "");
|
||||
string functionName = "array_nextElement_" + _type.identifier();
|
||||
@ -2447,7 +2447,7 @@ string YulUtilFunctions::copyArrayFromStorageToMemoryFunction(ArrayType const& _
|
||||
solAssert(_to.memoryStride() == 32, "");
|
||||
solAssert(_to.baseType()->dataStoredIn(DataLocation::Memory), "");
|
||||
solAssert(_from.baseType()->dataStoredIn(DataLocation::Storage), "");
|
||||
solAssert(!_from.isByteArray(), "");
|
||||
solAssert(!_from.isByteArrayOrString(), "");
|
||||
solAssert(*_to.withLocation(DataLocation::Storage, _from.isPointer()) == _from, "");
|
||||
return Whiskers(R"(
|
||||
function <functionName>(slot) -> memPtr {
|
||||
@ -2755,7 +2755,7 @@ string YulUtilFunctions::updateStorageValueFunction(
|
||||
solAssert(_fromType.category() == Type::Category::StringLiteral, "");
|
||||
solAssert(toReferenceType->category() == Type::Category::Array, "");
|
||||
auto const& toArrayType = dynamic_cast<ArrayType const&>(*toReferenceType);
|
||||
solAssert(toArrayType.isByteArray(), "");
|
||||
solAssert(toArrayType.isByteArrayOrString(), "");
|
||||
|
||||
return Whiskers(R"(
|
||||
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);
|
||||
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));
|
||||
}
|
||||
solAssert(_to.category() == Type::Category::Array);
|
||||
@ -3224,7 +3224,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
|
||||
|
||||
solAssert(
|
||||
fromType.arrayType().isImplicitlyConvertibleTo(targetType) ||
|
||||
(fromType.arrayType().isByteArray() && targetType.isByteArray())
|
||||
(fromType.arrayType().isByteArrayOrString() && targetType.isByteArrayOrString())
|
||||
);
|
||||
solAssert(
|
||||
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);
|
||||
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));
|
||||
}
|
||||
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)
|
||||
{
|
||||
solAssert(_from.isByteArray() && !_from.isString(), "");
|
||||
solAssert(_from.isByteArrayOrString() && !_from.isString(), "");
|
||||
solAssert(_from.isDynamicallySized(), "");
|
||||
string functionName = "convert_bytes_to_fixedbytes_from_" + _from.identifier() + "_to_" + _to.identifier();
|
||||
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))
|
||||
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.
|
||||
if (_to.location() == DataLocation::Storage)
|
||||
solAssert(
|
||||
(_to.isPointer() || (_from.isByteArray() && _to.isByteArray())) &&
|
||||
(_to.isPointer() || (_from.isByteArrayOrString() && _to.isByteArrayOrString())) &&
|
||||
_from.location() == DataLocation::Storage,
|
||||
"Invalid conversion to storage type."
|
||||
);
|
||||
@ -4238,7 +4238,7 @@ string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const
|
||||
}
|
||||
else if (_to.category() == Type::Category::Array)
|
||||
{
|
||||
solAssert(dynamic_cast<ArrayType const&>(_to).isByteArray(), "");
|
||||
solAssert(dynamic_cast<ArrayType const&>(_to).isByteArrayOrString(), "");
|
||||
Whiskers templ(R"(
|
||||
function <functionName>() -> converted {
|
||||
converted := <copyLiteralToMemory>()
|
||||
|
@ -677,7 +677,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
continue;
|
||||
if (
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]);
|
||||
arrayType && !arrayType->isByteArray()
|
||||
arrayType && !arrayType->isByteArrayOrString()
|
||||
)
|
||||
continue;
|
||||
|
||||
@ -698,7 +698,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
solAssert(returnTypes.size() == 1, "");
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes.front());
|
||||
if (arrayType)
|
||||
solAssert(arrayType->isByteArray(), "");
|
||||
solAssert(arrayType->isByteArrayOrString(), "");
|
||||
vector<string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots();
|
||||
returnVariables += retVars;
|
||||
code += Whiskers(R"(
|
||||
|
@ -2088,7 +2088,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
else if (dynamic_cast<UserDefinedValueType const*>(&actualType))
|
||||
solAssert(member == "wrap" || member == "unwrap");
|
||||
else if (auto const* arrayType = dynamic_cast<ArrayType const*>(&actualType))
|
||||
solAssert(arrayType->isByteArray() && member == "concat");
|
||||
solAssert(arrayType->isByteArrayOrString() && member == "concat");
|
||||
else
|
||||
// The old code generator had a generic "else" case here
|
||||
// without any specific code being generated,
|
||||
@ -2226,7 +2226,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
|
||||
setLValue(_indexAccess, IRLValue{
|
||||
*arrayType.baseType(),
|
||||
IRLValue::Memory{memAddress, arrayType.isByteArray()}
|
||||
IRLValue::Memory{memAddress, arrayType.isByteArrayOrString()}
|
||||
});
|
||||
break;
|
||||
}
|
||||
@ -2240,7 +2240,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
", " +
|
||||
expressionAsType(*_indexAccess.indexExpression(), *TypeProvider::uint256()) +
|
||||
")";
|
||||
if (arrayType.isByteArray())
|
||||
if (arrayType.isByteArrayOrString())
|
||||
define(_indexAccess) <<
|
||||
m_utils.cleanupFunction(*arrayType.baseType()) <<
|
||||
"(calldataload(" <<
|
||||
|
@ -953,7 +953,7 @@ bool isReturnedFromStructGetter(Type const* _type)
|
||||
if (category == Type::Category::Mapping)
|
||||
return false;
|
||||
if (category == Type::Category::Array)
|
||||
return dynamic_cast<ArrayType const&>(*_type).isByteArray();
|
||||
return dynamic_cast<ArrayType const&>(*_type).isByteArrayOrString();
|
||||
// default
|
||||
return true;
|
||||
}
|
||||
@ -990,7 +990,7 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
|
||||
{
|
||||
if (
|
||||
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(), "");
|
||||
@ -1071,7 +1071,7 @@ void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall)
|
||||
if (auto sliceType = dynamic_cast<ArraySliceType const*>(argType))
|
||||
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));
|
||||
bytesToFixedBytesAssertions(*array, _funCall);
|
||||
@ -2695,14 +2695,14 @@ Expression const* SMTEncoder::cleanExpression(Expression const& _expr)
|
||||
auto typeType = dynamic_cast<TypeType const*>(functionCall->expression().annotation().type);
|
||||
solAssert(typeType, "");
|
||||
if (auto const* arrayType = dynamic_cast<ArrayType const*>(typeType->actualType()))
|
||||
if (arrayType->isByteArray())
|
||||
if (arrayType->isByteArrayOrString())
|
||||
{
|
||||
// this is a cast to `bytes`
|
||||
solAssert(functionCall->arguments().size() == 1, "");
|
||||
Expression const& arg = *functionCall->arguments()[0];
|
||||
if (
|
||||
auto const* argArrayType = dynamic_cast<ArrayType const*>(arg.annotation().type);
|
||||
argArrayType && argArrayType->isByteArray()
|
||||
argArrayType && argArrayType->isByteArrayOrString()
|
||||
)
|
||||
return cleanExpression(arg);
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
auto sliceArrayType = dynamic_cast<ArraySliceType const*>(&_type);
|
||||
ArrayType const* arrayType = sliceArrayType ? &sliceArrayType->arrayType() : dynamic_cast<ArrayType const*>(&_type);
|
||||
if (
|
||||
(arrayType && (arrayType->isString() || arrayType->isByteArray())) ||
|
||||
(arrayType && (arrayType->isString() || arrayType->isByteArrayOrString())) ||
|
||||
_type.category() == frontend::Type::Category::StringLiteral
|
||||
)
|
||||
tupleName = "bytes";
|
||||
|
@ -176,7 +176,7 @@ Json::Value ABI::formatType(
|
||||
ret["type"] = _encodingType.canonicalName() + suffix;
|
||||
else if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(&_encodingType))
|
||||
{
|
||||
if (arrayType->isByteArray())
|
||||
if (arrayType->isByteArrayOrString())
|
||||
ret["type"] = _encodingType.canonicalName() + suffix;
|
||||
else
|
||||
{
|
||||
|
@ -94,7 +94,7 @@ void StorageLayout::generate(Type const* _type)
|
||||
}
|
||||
else if (auto arrayType = dynamic_cast<ArrayType const*>(_type))
|
||||
{
|
||||
if (arrayType->isByteArray())
|
||||
if (arrayType->isByteArrayOrString())
|
||||
typeInfo["encoding"] = "bytes";
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user