mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Refactoring of errors and fixes for various ICEs.
This commit is contained in:
parent
df1809f8da
commit
b744a56801
@ -518,19 +518,14 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
|
|||||||
m_errorReporter.typeError(_variable.location(), "Internal or recursive type is not allowed for public state variables.");
|
m_errorReporter.typeError(_variable.location(), "Internal or recursive type is not allowed for public state variables.");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (varType->category())
|
if (auto referenceType = dynamic_cast<ReferenceType const*>(varType))
|
||||||
{
|
{
|
||||||
case Type::Category::Array:
|
auto result = referenceType->validForLocation(referenceType->location());
|
||||||
if (auto arrayType = dynamic_cast<ArrayType const*>(varType))
|
if (!result)
|
||||||
if (
|
{
|
||||||
((arrayType->location() == DataLocation::Memory) ||
|
solAssert(!result.message().empty(), "Expected detailed error message");
|
||||||
(arrayType->location() == DataLocation::CallData)) &&
|
m_errorReporter.typeError(_variable.location(), result.message());
|
||||||
!arrayType->validForCalldata()
|
}
|
||||||
)
|
|
||||||
m_errorReporter.typeError(_variable.location(), "Array is too large to be encoded.");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -617,12 +617,20 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c
|
|||||||
else if (isLocalVariable())
|
else if (isLocalVariable())
|
||||||
{
|
{
|
||||||
solAssert(typeName(), "");
|
solAssert(typeName(), "");
|
||||||
solAssert(typeName()->annotation().type, "Can only be called after reference resolution");
|
auto getDataLocations = [](TypePointer _type, auto&& _recursion) -> set<Location> {
|
||||||
if (typeName()->annotation().type->category() == Type::Category::Mapping)
|
solAssert(_type, "Can only be called after reference resolution");
|
||||||
return set<Location>{ Location::Storage };
|
switch (_type->category())
|
||||||
else
|
{
|
||||||
// TODO: add Location::Calldata once implemented for local variables.
|
case Type::Category::Array:
|
||||||
return set<Location>{ Location::Memory, Location::Storage };
|
return _recursion(dynamic_cast<ArrayType const*>(_type)->baseType(), _recursion);
|
||||||
|
case Type::Category::Mapping:
|
||||||
|
return set<Location>{ Location::Storage };
|
||||||
|
default:
|
||||||
|
// TODO: add Location::Calldata once implemented for local variables.
|
||||||
|
return set<Location>{ Location::Memory, Location::Storage };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return getDataLocations(typeName()->annotation().type, getDataLocations);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// Struct members etc.
|
// Struct members etc.
|
||||||
|
@ -1649,12 +1649,35 @@ bool ArrayType::operator==(Type const& _other) const
|
|||||||
return isDynamicallySized() || length() == other.length();
|
return isDynamicallySized() || length() == other.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArrayType::validForCalldata() const
|
BoolResult ArrayType::validForLocation(DataLocation _loc) const
|
||||||
{
|
{
|
||||||
if (auto arrayBaseType = dynamic_cast<ArrayType const*>(baseType()))
|
if (auto arrayBaseType = dynamic_cast<ArrayType const*>(baseType()))
|
||||||
if (!arrayBaseType->validForCalldata())
|
{
|
||||||
return false;
|
BoolResult result = arrayBaseType->validForLocation(_loc);
|
||||||
return isDynamicallySized() || unlimitedStaticCalldataSize(true) <= numeric_limits<unsigned>::max();
|
if (!result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (isDynamicallySized())
|
||||||
|
return true;
|
||||||
|
switch (_loc)
|
||||||
|
{
|
||||||
|
case DataLocation::Memory:
|
||||||
|
{
|
||||||
|
bigint size = bigint(length()) * m_baseType->memoryHeadSize();
|
||||||
|
if (size >= numeric_limits<unsigned>::max())
|
||||||
|
return BoolResult::err("Type too large for memory.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DataLocation::CallData:
|
||||||
|
{
|
||||||
|
if (unlimitedStaticCalldataSize(true) >= numeric_limits<unsigned>::max())
|
||||||
|
return BoolResult::err("Type too large for calldata.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DataLocation::Storage:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bigint ArrayType::unlimitedStaticCalldataSize(bool _padded) const
|
bigint ArrayType::unlimitedStaticCalldataSize(bool _padded) const
|
||||||
@ -2272,6 +2295,18 @@ TypeResult StructType::interfaceType(bool _inLibrary) const
|
|||||||
return *m_interfaceType_library;
|
return *m_interfaceType_library;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoolResult StructType::validForLocation(DataLocation _loc) const
|
||||||
|
{
|
||||||
|
for (auto const& member: m_struct.members())
|
||||||
|
if (auto referenceType = dynamic_cast<ReferenceType const*>(member->annotation().type))
|
||||||
|
{
|
||||||
|
BoolResult result = referenceType->validForLocation(_loc);
|
||||||
|
if (!result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool StructType::recursive() const
|
bool StructType::recursive() const
|
||||||
{
|
{
|
||||||
solAssert(m_struct.annotation().recursive.has_value(), "Called StructType::recursive() before DeclarationTypeChecker.");
|
solAssert(m_struct.annotation().recursive.has_value(), "Called StructType::recursive() before DeclarationTypeChecker.");
|
||||||
|
@ -706,6 +706,9 @@ public:
|
|||||||
/// never change the contents of the original value.
|
/// never change the contents of the original value.
|
||||||
bool isPointer() const;
|
bool isPointer() const;
|
||||||
|
|
||||||
|
/// @returns true if this is valid to be stored in data location _loc
|
||||||
|
virtual BoolResult validForLocation(DataLocation _loc) const = 0;
|
||||||
|
|
||||||
bool operator==(ReferenceType const& _other) const
|
bool operator==(ReferenceType const& _other) const
|
||||||
{
|
{
|
||||||
return location() == _other.location() && isPointer() == _other.isPointer();
|
return location() == _other.location() && isPointer() == _other.isPointer();
|
||||||
@ -772,8 +775,7 @@ public:
|
|||||||
TypePointer decodingType() const override;
|
TypePointer decodingType() const override;
|
||||||
TypeResult interfaceType(bool _inLibrary) const override;
|
TypeResult interfaceType(bool _inLibrary) const override;
|
||||||
|
|
||||||
/// @returns true if this is valid to be stored in calldata
|
BoolResult validForLocation(DataLocation _loc) const override;
|
||||||
bool validForCalldata() const;
|
|
||||||
|
|
||||||
/// @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 isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; }
|
||||||
@ -827,8 +829,7 @@ public:
|
|||||||
bool canLiveOutsideStorage() const override { return m_arrayType.canLiveOutsideStorage(); }
|
bool canLiveOutsideStorage() const override { return m_arrayType.canLiveOutsideStorage(); }
|
||||||
std::string toString(bool _short) const override;
|
std::string toString(bool _short) const override;
|
||||||
|
|
||||||
/// @returns true if this is valid to be stored in calldata
|
BoolResult validForLocation(DataLocation _loc) const override { return m_arrayType.validForLocation(_loc); }
|
||||||
bool validForCalldata() const { return m_arrayType.validForCalldata(); }
|
|
||||||
|
|
||||||
ArrayType const& arrayType() const { return m_arrayType; }
|
ArrayType const& arrayType() const { return m_arrayType; }
|
||||||
u256 memoryDataSize() const override { solAssert(false, ""); }
|
u256 memoryDataSize() const override { solAssert(false, ""); }
|
||||||
@ -934,6 +935,8 @@ public:
|
|||||||
Type const* encodingType() const override;
|
Type const* encodingType() const override;
|
||||||
TypeResult interfaceType(bool _inLibrary) const override;
|
TypeResult interfaceType(bool _inLibrary) const override;
|
||||||
|
|
||||||
|
BoolResult validForLocation(DataLocation _loc) const override;
|
||||||
|
|
||||||
bool recursive() const;
|
bool recursive() const;
|
||||||
|
|
||||||
std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const override;
|
std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const override;
|
||||||
|
@ -7,3 +7,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
|
// TypeError: (226-234): Type too large for memory.
|
||||||
|
@ -2,4 +2,4 @@ contract C {
|
|||||||
function f(bytes32[1263941234127518272] memory) public pure {}
|
function f(bytes32[1263941234127518272] memory) public pure {}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (26-61): Array is too large to be encoded.
|
// TypeError: (26-61): Type too large for memory.
|
||||||
|
@ -2,10 +2,8 @@ contract C {
|
|||||||
function f(bytes32[1263941234127518272][500] memory) public pure {}
|
function f(bytes32[1263941234127518272][500] memory) public pure {}
|
||||||
function f(uint[2**30][] memory) public pure {}
|
function f(uint[2**30][] memory) public pure {}
|
||||||
function f(uint[2**30][2**30][] memory) public pure {}
|
function f(uint[2**30][2**30][] memory) public pure {}
|
||||||
function f(uint[2**16][2**16][] memory) public pure {}
|
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (26-66): Array is too large to be encoded.
|
// TypeError: (26-66): Type too large for memory.
|
||||||
// TypeError: (96-116): Array is too large to be encoded.
|
// TypeError: (96-116): Type too large for memory.
|
||||||
// TypeError: (146-173): Array is too large to be encoded.
|
// TypeError: (146-173): Type too large for memory.
|
||||||
// TypeError: (203-230): Array is too large to be encoded.
|
|
||||||
|
@ -5,5 +5,5 @@ contract C {
|
|||||||
function f(uint[2**30][2**30][][] memory) public pure {}
|
function f(uint[2**30][2**30][][] memory) public pure {}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (61-101): Array is too large to be encoded.
|
// TypeError: (61-101): Type too large for memory.
|
||||||
// TypeError: (131-160): Array is too large to be encoded.
|
// TypeError: (131-160): Type too large for memory.
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
contract C {
|
||||||
|
struct X { bytes31 [ 3 ] x1 ;
|
||||||
|
uint x2 ;
|
||||||
|
}
|
||||||
|
struct S { uint256 [ ] [ 0.425781 ether ] s1 ;
|
||||||
|
uint [ 2 ** 0xFF ] [ 2 ** 0x42 ] s2 ;
|
||||||
|
X s3 ;
|
||||||
|
mapping ( uint => address payable ) c ;
|
||||||
|
uint [ 9 hours ** 16 ] d ;
|
||||||
|
string s ;
|
||||||
|
}
|
||||||
|
function f ( ) public { function ( function ( bytes9 , uint ) external pure returns ( uint ) , uint ) external pure returns ( uint ) [ 3 ] memory s2 ;
|
||||||
|
S memory s ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (530-540): Type too large for memory.
|
@ -0,0 +1,12 @@
|
|||||||
|
contract C {
|
||||||
|
struct R { uint[10][10] y; }
|
||||||
|
struct S { uint a; uint b; R d; uint[20][20][2999999999999999999999999990] c; }
|
||||||
|
function f() public pure {
|
||||||
|
C.S memory y;
|
||||||
|
C.S[10] memory z;
|
||||||
|
y.a < 2;
|
||||||
|
z; y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (169-181): Type too large for memory.
|
@ -0,0 +1,7 @@
|
|||||||
|
contract C {
|
||||||
|
function h ( bool flag ) public returns ( bool c ) {
|
||||||
|
mapping ( string => uint24 ) [ 1 ] memory val ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (91-136): Data location must be "storage" for variable, but "memory" was given.
|
@ -0,0 +1,13 @@
|
|||||||
|
contract Test {
|
||||||
|
struct RecursiveStruct {
|
||||||
|
address payable d ;
|
||||||
|
mapping ( uint => address payable ) c ;
|
||||||
|
mapping ( uint => address payable [ ] ) d ;
|
||||||
|
}
|
||||||
|
function func ( ) private pure {
|
||||||
|
RecursiveStruct [ 1 ] memory val ;
|
||||||
|
val ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError: (157-198): Identifier already declared.
|
@ -4,4 +4,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (47-77): Type mapping(uint256 => uint256)[] memory is only valid in storage.
|
// TypeError: (47-77): Data location must be "storage" for variable, but "memory" was given.
|
||||||
|
@ -3,4 +3,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (28-56): Array is too large to be encoded.
|
// TypeError: (28-56): Type too large for calldata.
|
||||||
|
@ -3,4 +3,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (28-54): Array is too large to be encoded.
|
// TypeError: (28-54): Type too large for memory.
|
||||||
|
@ -3,4 +3,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (28-54): Array is too large to be encoded.
|
// TypeError: (28-54): Type too large for memory.
|
||||||
|
Loading…
Reference in New Issue
Block a user