added syntaxt tests and updated the TypeChecker logic.

This commit is contained in:
Saw-mon & Natalie 2023-05-21 16:41:06 +01:00 committed by Anton Bukov
parent 8023619d5c
commit 84918fb01e
18 changed files with 193 additions and 0 deletions

View File

@ -3393,7 +3393,31 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "interfaceId")
annotation.isPure = true;
else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "typehash")
{
annotation.isPure = true;
auto accessedStructType = dynamic_cast<StructType const*>(magicType->typeArgument());
solAssert(accessedStructType, "typehash requested on a non struct type.");
if (accessedStructType->recursive()) {
m_errorReporter.typeError(
9298_error,
_memberAccess.location(),
"\"typehash\" cannot be used for recursive structs."
);
}
for (auto const& member: accessedStructType->members(currentDefinitionScope()))
{
if (!member.type->isEIP712AllowedStructMemberType())
{
m_errorReporter.typeError(
9518_error,
_memberAccess.location(),
"\"typehash\" cannot be used for structs with members of \"" + member.type->humanReadableName() + "\" type."
);
}
}
}
else if (
magicType->kind() == MagicType::Kind::MetaType &&
(memberName == "min" || memberName == "max")

View File

@ -358,6 +358,7 @@ public:
virtual std::string canonicalName() const { return toString(true); }
virtual std::string humanReadableName() const { return toString(); }
virtual std::string eip712TypeName() const { return encodingType()->toString(true); }
virtual bool isEIP712AllowedStructMemberType() const { return false; }
/// @returns the signature of this type in external functions, i.e. `uint256` for integers
/// or `(uint256,bytes8)[2]` for an array of structs. If @a _structsByName,
/// structs are given by canonical name like `ContractName.StructName[2]`.
@ -458,6 +459,7 @@ public:
bool leftAligned() const override { return false; }
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
bool isEIP712AllowedStructMemberType() const override { return true; }
MemberList::MemberMap nativeMembers(ASTNode const*) const override;
@ -503,6 +505,7 @@ public:
bool leftAligned() const override { return false; }
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
bool isEIP712AllowedStructMemberType() const override { return true; }
std::string toString(bool _withoutDataLocation) const override;
@ -662,6 +665,8 @@ public:
return nullptr;
}
bool isEIP712AllowedStructMemberType() const override { return true; }
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
@ -700,6 +705,7 @@ public:
bool leftAligned() const override { return true; }
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
bool isEIP712AllowedStructMemberType() const override { return true; }
std::string toString(bool) const override { return "bytes" + util::toString(m_bytes); }
MemberList::MemberMap nativeMembers(ASTNode const*) const override;
@ -728,6 +734,7 @@ public:
bool leftAligned() const override { return false; }
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
bool isEIP712AllowedStructMemberType() const override { return true; }
std::string toString(bool) const override { return "bool"; }
u256 literalValue(Literal const* _literal) const override;
@ -865,6 +872,7 @@ public:
u256 storageSize() const override;
bool containsNestedMapping() const override { return m_baseType->containsNestedMapping(); }
bool nameable() const override { return true; }
bool isEIP712AllowedStructMemberType() const override { return true; }
std::string toString(bool _withoutDataLocation) const override;
std::string humanReadableName() const override;
@ -978,6 +986,7 @@ public:
bool leftAligned() const override { solAssert(!isSuper(), ""); return false; }
bool isValueType() const override { return !isSuper(); }
bool nameable() const override { return !isSuper(); }
bool isEIP712AllowedStructMemberType() const override { return true; }
std::string toString(bool _withoutDataLocation) const override;
std::string canonicalName() const override;
@ -1040,6 +1049,7 @@ public:
u256 storageSize() const override;
bool containsNestedMapping() const override;
bool nameable() const override { return true; }
bool isEIP712AllowedStructMemberType() const override { return true; }
std::string toString(bool _withoutDataLocation) const override;
MemberList::MemberMap nativeMembers(ASTNode const* _currentScope) const override;

View File

@ -0,0 +1,7 @@
contract C {
struct S {
uint256[][10][] x;
}
bytes32 constant h = type(S).typehash;
}

View File

@ -0,0 +1,5 @@
contract C {
bytes32 x = type(C).typehash;
}
// ----
// TypeError 9582: (29-45): Member "typehash" not found or not visible after argument-dependent lookup in type(contract C).

View File

@ -0,0 +1,9 @@
contract C {
enum E {
VALUE
}
bytes32 h = type(E).typehash;
}
// ----
// TypeError 9582: (63-79): Member "typehash" not found or not visible after argument-dependent lookup in type(enum C.E).

View File

@ -0,0 +1,14 @@
contract C {
enum E {
VALUE
}
struct S {
E e;
}
bytes32 h = type(S).typehash;
}
// ----
// TypeError 9518: (98-114): "typehash" cannot be used for structs with members of "enum C.E" type.

View File

@ -0,0 +1,9 @@
contract C {
struct S {
fixed128x18 x;
}
bytes32 h = type(S).typehash;
}
// ----
// TypeError 9518: (74-90): "typehash" cannot be used for structs with members of "fixed128x18" type.

View File

@ -0,0 +1,9 @@
contract C {
struct S {
function(uint256) internal returns(uint256) f;
}
bytes32 h = type(S).typehash;
}
// ----
// TypeError 9518: (106-122): "typehash" cannot be used for structs with members of "function (uint256) returns (uint256)" type.

View File

@ -0,0 +1,9 @@
contract C {
struct S {
mapping (uint256 => uint256) x;
}
bytes32 h = type(S).typehash;
}
// ----
// TypeError 9518: (92-108): "typehash" cannot be used for structs with members of "mapping(uint256 => uint256)" type.

View File

@ -0,0 +1,9 @@
contract C {
struct S {
ufixed128x18 x;
}
bytes32 h = type(S).typehash;
}
// ----
// TypeError 9518: (75-91): "typehash" cannot be used for structs with members of "ufixed128x18" type.

View File

@ -0,0 +1,10 @@
type T is uint256;
contract C {
struct S {
T t;
}
bytes32 h = type(S).typehash;
}
// ----
// TypeError 9518: (83-99): "typehash" cannot be used for structs with members of "T" type.

View File

@ -0,0 +1,9 @@
contract C {
struct S {
uint256 x;
}
function f() public pure returns(bytes32) {
return type(S).typehash;
}
}

View File

@ -0,0 +1,9 @@
contract C {
struct S {
S[] s;
}
bytes32 h = type(S).typehash;
}
// ----
// TypeError 9298: (68-84): "typehash" cannot be used for recursive structs.

View File

@ -0,0 +1,14 @@
contract A {
struct S {
C.S[] s;
}
}
contract C {
struct S {
A.S s;
}
bytes32 h = type(S).typehash;
}
// ----
// TypeError 9298: (121-137): "typehash" cannot be used for recursive structs.

View File

@ -0,0 +1,15 @@
contract C {
struct S {
uint256 x;
}
function f1(S calldata s) public pure returns(bytes32 h) {
h = type(s).typehash; // should fail
}
function f3(S calldata s) public pure returns(bytes32 h) {
h = type(S).typehash;
}
}
// ----
// TypeError 4259: (134-135): Invalid type for argument in the function call. An enum type, contract type, struct type or an integer type is required, but struct C.S calldata provided.

View File

@ -0,0 +1,15 @@
contract C {
struct S {
uint256 x;
}
function f1(S memory s) public pure returns(bytes32 h) {
h = type(s).typehash; // should fail
}
function f3(S calldata s) public pure returns(bytes32 h) {
h = type(S).typehash;
}
}
// ----
// TypeError 4259: (132-133): Invalid type for argument in the function call. An enum type, contract type, struct type or an integer type is required, but struct C.S memory provided.

View File

@ -0,0 +1,5 @@
contract C {
bytes32 h = type(uint256).typehash;
}
// ----
// TypeError 9582: (29-51): Member "typehash" not found or not visible after argument-dependent lookup in type(uint256).

View File

@ -0,0 +1,11 @@
contract C {
struct S {
uint256 x;
}
function f() public view returns(bytes32) { // can be pure
return type(S).typehash;
}
}
// ----
// Warning 2018: (58-155): Function state mutability can be restricted to pure