Skip to content

Commit 89bb79b

Browse files
Merge pull request #12593 from nishant-sachdeva/allowing_string_concat_operations
Changed interpretation of isByteArray() to return True only for Byte Type. Cases where both Byte And String Types are required have been provided with isByteArrayOrString() function.
2 parents a05d2b3 + cc6344c commit 89bb79b

15 files changed

+118
-116
lines changed

libsolidity/analysis/DeclarationTypeChecker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
441441
{
442442
bool allowed = false;
443443
if (auto arrayType = dynamic_cast<ArrayType const*>(type))
444-
allowed = arrayType->isByteArray();
444+
allowed = arrayType->isByteArrayOrString();
445445
if (!allowed)
446446
m_errorReporter.fatalTypeError(9259_error, _variable.location(), "Only constants of value type and byte array type are implemented.");
447447
}

libsolidity/analysis/TypeChecker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,15 +1783,15 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
17831783
(
17841784
(
17851785
resultArrayType->isPointer() ||
1786-
(argArrayType->isByteArray() && resultArrayType->isByteArray())
1786+
(argArrayType->isByteArrayOrString() && resultArrayType->isByteArrayOrString())
17871787
) &&
17881788
resultArrayType->location() == DataLocation::Storage
17891789
),
17901790
"Invalid explicit conversion to storage type."
17911791
);
17921792
else
17931793
solAssert(
1794-
argArrayType->isByteArray() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes,
1794+
argArrayType->isByteArray() && resultType->category() == Type::Category::FixedBytes,
17951795
""
17961796
);
17971797
}

libsolidity/ast/Types.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,7 @@ BoolResult StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo)
12061206
);
12071207
return
12081208
arrayType->location() != DataLocation::CallData &&
1209-
arrayType->isByteArray() &&
1209+
arrayType->isByteArrayOrString() &&
12101210
!(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer());
12111211
}
12121212
else
@@ -1571,11 +1571,11 @@ BoolResult ArrayType::isExplicitlyConvertibleTo(Type const& _convertTo) const
15711571
return true;
15721572
// allow conversion bytes <-> string and bytes -> bytesNN
15731573
if (_convertTo.category() != category())
1574-
return isByteArray() && !isString() && _convertTo.category() == Type::Category::FixedBytes;
1574+
return isByteArray() && _convertTo.category() == Type::Category::FixedBytes;
15751575
auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
15761576
if (convertTo.location() != location())
15771577
return false;
1578-
if (!isByteArray() || !convertTo.isByteArray())
1578+
if (!isByteArrayOrString() || !convertTo.isByteArrayOrString())
15791579
return false;
15801580
return true;
15811581
}
@@ -1585,7 +1585,7 @@ string ArrayType::richIdentifier() const
15851585
string id;
15861586
if (isString())
15871587
id = "t_string";
1588-
else if (isByteArray())
1588+
else if (isByteArrayOrString())
15891589
id = "t_bytes";
15901590
else
15911591
{
@@ -1751,7 +1751,7 @@ string ArrayType::toString(bool _short) const
17511751
string ret;
17521752
if (isString())
17531753
ret = "string";
1754-
else if (isByteArray())
1754+
else if (isByteArrayOrString())
17551755
ret = "bytes";
17561756
else
17571757
{
@@ -1770,7 +1770,7 @@ string ArrayType::canonicalName() const
17701770
string ret;
17711771
if (isString())
17721772
ret = "string";
1773-
else if (isByteArray())
1773+
else if (isByteArrayOrString())
17741774
ret = "bytes";
17751775
else
17761776
{
@@ -1784,7 +1784,7 @@ string ArrayType::canonicalName() const
17841784

17851785
string ArrayType::signatureInExternalFunction(bool _structsByName) const
17861786
{
1787-
if (isByteArray())
1787+
if (isByteArrayOrString())
17881788
return canonicalName();
17891789
else
17901790
{
@@ -1899,7 +1899,7 @@ u256 ArrayType::memoryDataSize() const
18991899
{
19001900
solAssert(!isDynamicallySized(), "");
19011901
solAssert(m_location == DataLocation::Memory, "");
1902-
solAssert(!isByteArray(), "");
1902+
solAssert(!isByteArrayOrString(), "");
19031903
bigint size = bigint(m_length) * m_baseType->memoryHeadSize();
19041904
solAssert(size <= numeric_limits<u256>::max(), "Array size does not fit u256.");
19051905
return u256(size);
@@ -2701,7 +2701,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
27012701
}
27022702
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
27032703
{
2704-
if (arrayType->isByteArray())
2704+
if (arrayType->isByteArrayOrString())
27052705
// Return byte arrays as whole.
27062706
break;
27072707
returnType = arrayType->baseType();
@@ -2720,7 +2720,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
27202720
if (member.type->category() != Category::Mapping)
27212721
{
27222722
if (auto arrayType = dynamic_cast<ArrayType const*>(member.type))
2723-
if (!arrayType->isByteArray())
2723+
if (!arrayType->isByteArrayOrString())
27242724
continue;
27252725
m_returnParameterTypes.push_back(TypeProvider::withLocationIfReference(
27262726
DataLocation::Memory,
@@ -3813,7 +3813,7 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
38133813
}
38143814
else if (
38153815
auto const* arrayType = dynamic_cast<ArrayType const*>(m_actualType);
3816-
arrayType && arrayType->isByteArray()
3816+
arrayType && arrayType->isByteArrayOrString()
38173817
)
38183818
members.emplace_back("concat", TypeProvider::function(
38193819
TypePointers{},

libsolidity/ast/Types.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -837,8 +837,10 @@ class ArrayType: public ReferenceType
837837

838838
BoolResult validForLocation(DataLocation _loc) const override;
839839

840+
/// @returns true if this is a byte array.
841+
bool isByteArray() const { return m_arrayKind == ArrayKind::Bytes; }
840842
/// @returns true if this is a byte array or a string
841-
bool isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; }
843+
bool isByteArrayOrString() const { return m_arrayKind != ArrayKind::Ordinary; }
842844
/// @returns true if this is a string
843845
bool isString() const { return m_arrayKind == ArrayKind::String; }
844846
Type const* baseType() const { solAssert(!!m_baseType, ""); return m_baseType; }
@@ -849,11 +851,11 @@ class ArrayType: public ReferenceType
849851
std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const override;
850852

851853
/// The offset to advance in calldata to move from one array element to the next.
852-
unsigned calldataStride() const { return isByteArray() ? 1 : m_baseType->calldataHeadSize(); }
854+
unsigned calldataStride() const { return isByteArrayOrString() ? 1 : m_baseType->calldataHeadSize(); }
853855
/// The offset to advance in memory to move from one array element to the next.
854-
unsigned memoryStride() const { return isByteArray() ? 1 : m_baseType->memoryHeadSize(); }
856+
unsigned memoryStride() const { return isByteArrayOrString() ? 1 : m_baseType->memoryHeadSize(); }
855857
/// The offset to advance in storage to move from one array element to the next.
856-
unsigned storageStride() const { return isByteArray() ? 1 : m_baseType->storageBytes(); }
858+
unsigned storageStride() const { return isByteArrayOrString() ? 1 : m_baseType->storageBytes(); }
857859

858860
void clearCache() const override;
859861

libsolidity/codegen/ABIFunctions.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -312,15 +312,15 @@ string ABIFunctions::abiEncodingFunction(
312312
{
313313
case DataLocation::CallData:
314314
if (
315-
fromArray->isByteArray() ||
315+
fromArray->isByteArrayOrString() ||
316316
*fromArray->baseType() == *TypeProvider::uint256() ||
317317
*fromArray->baseType() == FixedBytesType(32)
318318
)
319319
return abiEncodingFunctionCalldataArrayWithoutCleanup(*fromArray, *toArray, _options);
320320
else
321321
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
322322
case DataLocation::Memory:
323-
if (fromArray->isByteArray())
323+
if (fromArray->isByteArrayOrString())
324324
return abiEncodingFunctionMemoryByteArray(*fromArray, *toArray, _options);
325325
else
326326
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
@@ -448,7 +448,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
448448

449449
solAssert(fromArrayType.location() == DataLocation::CallData, "");
450450
solAssert(
451-
fromArrayType.isByteArray() ||
451+
fromArrayType.isByteArrayOrString() ||
452452
*fromArrayType.baseType() == *TypeProvider::uint256() ||
453453
*fromArrayType.baseType() == FixedBytesType(32),
454454
""
@@ -468,7 +468,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
468468
_to.identifier() +
469469
_options.toFunctionNameSuffix();
470470
return createFunction(functionName, [&]() {
471-
bool needsPadding = _options.padded && fromArrayType.isByteArray();
471+
bool needsPadding = _options.padded && fromArrayType.isByteArrayOrString();
472472
if (fromArrayType.isDynamicallySized())
473473
{
474474
Whiskers templ(R"(
@@ -482,7 +482,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
482482
)");
483483
templ("storeLength", arrayStoreLengthForEncodingFunction(toArrayType, _options));
484484
templ("functionName", functionName);
485-
if (fromArrayType.isByteArray() || fromArrayType.calldataStride() == 1)
485+
if (fromArrayType.isByteArrayOrString() || fromArrayType.calldataStride() == 1)
486486
templ("scaleLengthByStride", "");
487487
else
488488
templ("scaleLengthByStride",
@@ -536,7 +536,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
536536

537537
solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), "");
538538
solAssert(_from.length() == _to.length(), "");
539-
solAssert(!_from.isByteArray(), "");
539+
solAssert(!_from.isByteArrayOrString(), "");
540540
if (_from.dataStoredIn(DataLocation::Storage))
541541
solAssert(_from.baseType()->storageBytes() > 16, "");
542542

@@ -647,10 +647,10 @@ string ABIFunctions::abiEncodingFunctionMemoryByteArray(
647647
solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), "");
648648
solAssert(_from.length() == _to.length(), "");
649649
solAssert(_from.dataStoredIn(DataLocation::Memory), "");
650-
solAssert(_from.isByteArray(), "");
650+
solAssert(_from.isByteArrayOrString(), "");
651651

652652
return createFunction(functionName, [&]() {
653-
solAssert(_to.isByteArray(), "");
653+
solAssert(_to.isByteArrayOrString(), "");
654654
Whiskers templ(R"(
655655
function <functionName>(value, pos) -> end {
656656
let length := <lengthFun>(value)
@@ -686,9 +686,9 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
686686
solAssert(_from.dataStoredIn(DataLocation::Storage), "");
687687

688688
return createFunction(functionName, [&]() {
689-
if (_from.isByteArray())
689+
if (_from.isByteArrayOrString())
690690
{
691-
solAssert(_to.isByteArray(), "");
691+
solAssert(_to.isByteArrayOrString(), "");
692692
Whiskers templ(R"(
693693
// <readableTypeNameFrom> -> <readableTypeNameTo>
694694
function <functionName>(value, pos) -> ret {
@@ -1168,7 +1168,7 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from
11681168
string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
11691169
{
11701170
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
1171-
if (_type.isByteArray())
1171+
if (_type.isByteArrayOrString())
11721172
return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory);
11731173
solAssert(_type.calldataStride() > 0, "");
11741174

@@ -1275,7 +1275,7 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
12751275
string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
12761276
{
12771277
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
1278-
solAssert(_type.isByteArray(), "");
1278+
solAssert(_type.isByteArrayOrString(), "");
12791279

12801280
string functionName =
12811281
"abi_decode_available_length_" +

0 commit comments

Comments
 (0)