DeclarationTypeChecker for UserDefinedValueTypes

- Checks for repetitions.
- Assigns types.
- Checks if the 'actual type' is an elementary type name.
- Checks if the 'actual type' is a value type.

Also added tests.
This commit is contained in:
hrkrshnn 2021-08-16 14:43:05 +02:00
parent 15452371d4
commit 0647039864
17 changed files with 113 additions and 0 deletions

View File

@ -140,6 +140,30 @@ bool DeclarationTypeChecker::visit(StructDefinition const& _struct)
return false; return false;
} }
void DeclarationTypeChecker::endVisit(UserDefinedValueTypeDefinition const& _userDefined)
{
TypeName const* typeName = _userDefined.underlyingType();
solAssert(typeName, "");
if (!dynamic_cast<ElementaryTypeName const*>(typeName))
m_errorReporter.fatalTypeError(
8657_error,
typeName->location(),
"The underlying type for a user defined value type has to be an elementary value type."
);
Type const* type = typeName->annotation().type;
solAssert(type, "");
solAssert(!dynamic_cast<UserDefinedValueType const*>(type), "");
if (!type->isValueType())
m_errorReporter.typeError(
8129_error,
_userDefined.location(),
"The underlying type of the user defined value type \"" +
_userDefined.name() +
"\" is not a value type."
);
}
void DeclarationTypeChecker::endVisit(UserDefinedTypeName const& _typeName) void DeclarationTypeChecker::endVisit(UserDefinedTypeName const& _typeName)
{ {
if (_typeName.annotation().type) if (_typeName.annotation().type)
@ -158,6 +182,8 @@ void DeclarationTypeChecker::endVisit(UserDefinedTypeName const& _typeName)
_typeName.annotation().type = TypeProvider::enumType(*enumDef); _typeName.annotation().type = TypeProvider::enumType(*enumDef);
else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration)) else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration))
_typeName.annotation().type = TypeProvider::contract(*contract); _typeName.annotation().type = TypeProvider::contract(*contract);
else if (auto userDefinedValueType = dynamic_cast<UserDefinedValueTypeDefinition const*>(declaration))
_typeName.annotation().type = TypeProvider::userDefinedValueType(*userDefinedValueType);
else else
{ {
_typeName.annotation().type = TypeProvider::emptyTuple(); _typeName.annotation().type = TypeProvider::emptyTuple();

View File

@ -60,6 +60,7 @@ private:
void endVisit(VariableDeclaration const& _variable) override; void endVisit(VariableDeclaration const& _variable) override;
bool visit(EnumDefinition const& _enum) override; bool visit(EnumDefinition const& _enum) override;
bool visit(StructDefinition const& _struct) override; bool visit(StructDefinition const& _struct) override;
void endVisit(UserDefinedValueTypeDefinition const& _userDefined) override;
bool visit(UsingForDirective const& _usingForDirective) override; bool visit(UsingForDirective const& _usingForDirective) override;
bool visit(InheritanceSpecifier const& _inheritanceSpecifier) override; bool visit(InheritanceSpecifier const& _inheritanceSpecifier) override;

View File

@ -0,0 +1,12 @@
type MyAddress is address;
type MyAddressPayable is address payable;
type MyInt is int;
type MyUInt is uint;
type MyInt128 is int128;
type MyUInt128 is uint128;
// TODO add fixed point type, when it's implemented
type MyFixedBytes32 is bytes32;
type MyFixedBytes1 is bytes1;
type MyBool is bool;
/// test to see if having NatSpec causes issues
type redundantNatSpec is bytes2;

View File

@ -0,0 +1,6 @@
type MyAddress is address;
function f() {
MyAddress a = MyAddress(5, 2);
}
// ----
// TypeError 2558: (60-75): Exactly one argument expected for explicit type conversion.

View File

@ -0,0 +1,6 @@
type MyAddress is address;
contract C {
type MyAddress is address;
}
// ----
// Warning 2519: (44-70): This declaration shadows an existing declaration.

View File

@ -0,0 +1,9 @@
type MyInt is int;
type MyInt is address;
contract C {
type MyAddress is address;
type MyAddress is address;
}
// ----
// DeclarationError 2333: (19-41): Identifier already declared.
// DeclarationError 2333: (90-116): Identifier already declared.

View File

@ -0,0 +1,3 @@
type MyBytes is bytes;
// ----
// TypeError 8129: (0-22): The underlying type of the user defined value type "MyBytes" is not a value type.

View File

@ -0,0 +1,4 @@
contract C {}
type MyContract is C;
// ----
// TypeError 8657: (33-34): The underlying type for a user defined value type has to be an elementary value type.

View File

@ -0,0 +1,3 @@
type MyFunction is function(uint) returns (uint);
// ----
// TypeError 8657: (19-49): The underlying type for a user defined value type has to be an elementary value type.

View File

@ -0,0 +1,3 @@
type MyInt is mapping(uint => uint);
// ----
// TypeError 8657: (14-35): The underlying type for a user defined value type has to be an elementary value type.

View File

@ -0,0 +1,3 @@
type MyString is string;
// ----
// TypeError 8129: (0-24): The underlying type of the user defined value type "MyString" is not a value type.

View File

@ -0,0 +1,7 @@
struct S {uint x;}
contract C {
type MyType is S;
}
// ----
// TypeError 8657: (52-53): The underlying type for a user defined value type has to be an elementary value type.

View File

@ -0,0 +1,4 @@
type MyInt1 is MyInt2;
type MyInt2 is MyInt1;
// ----
// TypeError 8657: (15-21): The underlying type for a user defined value type has to be an elementary value type.

View File

@ -0,0 +1,3 @@
type MyFunction is function(MyFunction) external returns(MyFunction);
// ----
// TypeError 8657: (19-69): The underlying type for a user defined value type has to be an elementary value type.

View File

@ -0,0 +1,13 @@
library L {
type MyInt is int;
}
contract C {
L.MyInt a;
type MyInt is int8;
}
contract D is C {
C.MyInt b;
L.MyInt c;
}

View File

@ -0,0 +1,7 @@
type MyInt is int;
type MyInt is int;
type MyAddress is address;
type MyAddress is uint;
// ----
// DeclarationError 2333: (19-37): Identifier already declared.
// DeclarationError 2333: (65-88): Identifier already declared.

View File

@ -0,0 +1,3 @@
type MyInt is MyInt;
// ----
// TypeError 8657: (14-19): The underlying type for a user defined value type has to be an elementary value type.