mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10055 from ethereum/userDefinedLibraryTypes
Disallow invalid use of library names as type names.
This commit is contained in:
commit
db4dd51739
@ -22,6 +22,7 @@ Bugfixes:
|
||||
* Code generator: Fix internal compiler error when referencing members via module name but not using the reference.
|
||||
* Code generator: Fix ``ABIEncoderV2`` pragma from the current module affecting inherited functions and applied modifiers.
|
||||
* Code generator: Use revert instead of invalid opcode for out-of-bounds array index access in getter.
|
||||
* Type Checker: Disallow invalid use of library names as type name.
|
||||
* Type Checker: Fix internal compiler error caused by storage parameters with nested mappings in libraries.
|
||||
* Name Resolver: Fix shadowing/same-name warnings for later declarations.
|
||||
* Contract Level Checker: Add missing check against inheriting functions with ABIEncoderV2 return types in ABIEncoderV1 contracts.
|
||||
|
@ -145,7 +145,11 @@ void DeclarationTypeChecker::endVisit(UserDefinedTypeName const& _typeName)
|
||||
else if (EnumDefinition const* enumDef = dynamic_cast<EnumDefinition const*>(declaration))
|
||||
_typeName.annotation().type = TypeProvider::enumType(*enumDef);
|
||||
else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration))
|
||||
{
|
||||
if (contract->isLibrary())
|
||||
m_errorReporter.typeError(1130_error, _typeName.location(), "Invalid use of a library name.");
|
||||
_typeName.annotation().type = TypeProvider::contract(*contract);
|
||||
}
|
||||
else
|
||||
{
|
||||
_typeName.annotation().type = TypeProvider::emptyTuple();
|
||||
@ -201,23 +205,19 @@ void DeclarationTypeChecker::endVisit(Mapping const& _mapping)
|
||||
return;
|
||||
|
||||
if (auto const* typeName = dynamic_cast<UserDefinedTypeName const*>(&_mapping.keyType()))
|
||||
{
|
||||
if (auto const* contractType = dynamic_cast<ContractType const*>(typeName->annotation().type))
|
||||
switch (typeName->annotation().type->category())
|
||||
{
|
||||
if (contractType->contractDefinition().isLibrary())
|
||||
case Type::Category::Enum:
|
||||
case Type::Category::Contract:
|
||||
break;
|
||||
default:
|
||||
m_errorReporter.fatalTypeError(
|
||||
1665_error,
|
||||
7804_error,
|
||||
typeName->location(),
|
||||
"Library types cannot be used as mapping keys."
|
||||
"Only elementary types, contract types or enums are allowed as mapping keys."
|
||||
);
|
||||
break;
|
||||
}
|
||||
else if (typeName->annotation().type->category() != Type::Category::Enum)
|
||||
m_errorReporter.fatalTypeError(
|
||||
7804_error,
|
||||
typeName->location(),
|
||||
"Only elementary types, contract types or enums are allowed as mapping keys."
|
||||
);
|
||||
}
|
||||
else
|
||||
solAssert(dynamic_cast<ElementaryTypeName const*>(&_mapping.keyType()), "");
|
||||
|
||||
@ -243,6 +243,7 @@ void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName)
|
||||
solAssert(!m_errorReporter.errors().empty(), "");
|
||||
return;
|
||||
}
|
||||
|
||||
solAssert(baseType->storageBytes() != 0, "Illegal base type of storage size zero for array.");
|
||||
if (Expression const* length = _typeName.length())
|
||||
{
|
||||
@ -393,13 +394,36 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
|
||||
|
||||
}
|
||||
|
||||
void DeclarationTypeChecker::endVisit(UsingForDirective const& _usingFor)
|
||||
bool DeclarationTypeChecker::visit(UsingForDirective const& _usingFor)
|
||||
{
|
||||
ContractDefinition const* library = dynamic_cast<ContractDefinition const*>(
|
||||
_usingFor.libraryName().annotation().referencedDeclaration
|
||||
);
|
||||
|
||||
if (!library || !library->isLibrary())
|
||||
m_errorReporter.fatalTypeError(4357_error, _usingFor.libraryName().location(), "Library name expected.");
|
||||
|
||||
_usingFor.libraryName().annotation().type = TypeProvider::contract(*library);
|
||||
if (_usingFor.typeName())
|
||||
_usingFor.typeName()->accept(*this);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeclarationTypeChecker::visit(InheritanceSpecifier const& _inheritanceSpecifier)
|
||||
{
|
||||
auto const* contract = dynamic_cast<ContractDefinition const*>(_inheritanceSpecifier.name().annotation().referencedDeclaration);
|
||||
solAssert(contract, "");
|
||||
if (contract->isLibrary())
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
2571_error,
|
||||
_inheritanceSpecifier.name().location(),
|
||||
"Libraries cannot be inherited from."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeclarationTypeChecker::check(ASTNode const& _node)
|
||||
|
@ -59,7 +59,8 @@ private:
|
||||
void endVisit(ArrayTypeName const& _typeName) override;
|
||||
void endVisit(VariableDeclaration const& _variable) override;
|
||||
bool visit(StructDefinition const& _struct) override;
|
||||
void endVisit(UsingForDirective const& _usingForDirective) override;
|
||||
bool visit(UsingForDirective const& _usingForDirective) override;
|
||||
bool visit(InheritanceSpecifier const& _inheritanceSpecifier) override;
|
||||
|
||||
langutil::ErrorReporter& m_errorReporter;
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
|
@ -276,9 +276,6 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
|
||||
if (m_currentContract->isInterface() && !base->isInterface())
|
||||
m_errorReporter.typeError(6536_error, _inheritance.location(), "Interfaces can only inherit from other interfaces.");
|
||||
|
||||
if (base->isLibrary())
|
||||
m_errorReporter.typeError(2571_error, _inheritance.location(), "Libraries cannot be inherited from.");
|
||||
|
||||
auto const& arguments = _inheritance.arguments();
|
||||
TypePointers parameterTypes;
|
||||
if (!base->isInterface())
|
||||
@ -508,9 +505,6 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
|
||||
TypePointer varType = _variable.annotation().type;
|
||||
solAssert(!!varType, "Variable type not provided.");
|
||||
|
||||
if (auto contractType = dynamic_cast<ContractType const*>(varType))
|
||||
if (contractType->contractDefinition().isLibrary())
|
||||
m_errorReporter.typeError(1273_error, _variable.location(), "The type of a variable cannot be a library.");
|
||||
if (_variable.value())
|
||||
{
|
||||
if (_variable.isStateVariable() && varType->containsNestedMapping())
|
||||
|
@ -0,0 +1,8 @@
|
||||
library L {}
|
||||
contract C {
|
||||
function f() public {
|
||||
L[] memory x;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1130: (51-52): Invalid use of a library name.
|
8
test/libsolidity/syntaxTests/array/library_array.sol
Normal file
8
test/libsolidity/syntaxTests/array/library_array.sol
Normal file
@ -0,0 +1,8 @@
|
||||
library L {}
|
||||
contract C {
|
||||
function f() public pure {
|
||||
new L[](2);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1130: (63-64): Invalid use of a library name.
|
11
test/libsolidity/syntaxTests/bound/using_for_library.sol
Normal file
11
test/libsolidity/syntaxTests/bound/using_for_library.sol
Normal file
@ -0,0 +1,11 @@
|
||||
library L {}
|
||||
library M {}
|
||||
contract C {
|
||||
using L for M;
|
||||
using M for L;
|
||||
using L for L;
|
||||
}
|
||||
// ----
|
||||
// TypeError 1130: (55-56): Invalid use of a library name.
|
||||
// TypeError 1130: (74-75): Invalid use of a library name.
|
||||
// TypeError 1130: (93-94): Invalid use of a library name.
|
@ -0,0 +1,8 @@
|
||||
library L {}
|
||||
contract C {
|
||||
function f() public pure {
|
||||
new L();
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1130: (63-64): Invalid use of a library name.
|
@ -0,0 +1,6 @@
|
||||
library L {}
|
||||
contract C {
|
||||
function f() public override (L) {}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1130: (57-58): Invalid use of a library name.
|
@ -6,5 +6,4 @@ contract test {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1273: (87-90): The type of a variable cannot be a library.
|
||||
// TypeError 9582: (100-103): Member "l" not found or not visible after argument-dependent lookup in library L.
|
||||
// TypeError 1130: (87-88): Invalid use of a library name.
|
||||
|
@ -1,6 +0,0 @@
|
||||
library L {}
|
||||
contract C {
|
||||
function f() public {
|
||||
new L();
|
||||
}
|
||||
}
|
@ -9,6 +9,6 @@ contract Y {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1273: (29-34): The type of a variable cannot be a library.
|
||||
// TypeError 1273: (50-57): The type of a variable cannot be a library.
|
||||
// TypeError 1273: (77-82): The type of a variable cannot be a library.
|
||||
// TypeError 1130: (29-30): Invalid use of a library name.
|
||||
// TypeError 1130: (50-51): Invalid use of a library name.
|
||||
// TypeError 1130: (77-78): Invalid use of a library name.
|
||||
|
@ -1,4 +1,9 @@
|
||||
library L {}
|
||||
contract C { mapping(L => bool) i; }
|
||||
contract C
|
||||
{
|
||||
mapping(bool => L) j;
|
||||
mapping(L => bool) i;
|
||||
}
|
||||
// ----
|
||||
// TypeError 1665: (34-35): Library types cannot be used as mapping keys.
|
||||
// TypeError 1130: (44-45): Invalid use of a library name.
|
||||
// TypeError 1130: (60-61): Invalid use of a library name.
|
||||
|
Loading…
Reference in New Issue
Block a user