mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Move mapping key checks to ReferencesResolver and make them fatal.
This commit is contained in:
parent
5214cb0e76
commit
9c3151748e
@ -224,15 +224,36 @@ void ReferencesResolver::endVisit(FunctionTypeName const& _typeName)
|
|||||||
_typeName.annotation().type = TypeProvider::function(_typeName);
|
_typeName.annotation().type = TypeProvider::function(_typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReferencesResolver::endVisit(Mapping const& _typeName)
|
void ReferencesResolver::endVisit(Mapping const& _mapping)
|
||||||
{
|
{
|
||||||
TypePointer keyType = _typeName.keyType().annotation().type;
|
if (auto const* typeName = dynamic_cast<UserDefinedTypeName const*>(&_mapping.keyType()))
|
||||||
TypePointer valueType = _typeName.valueType().annotation().type;
|
{
|
||||||
|
if (auto const* contractType = dynamic_cast<ContractType const*>(typeName->annotation().type))
|
||||||
|
{
|
||||||
|
if (contractType->contractDefinition().isLibrary())
|
||||||
|
m_errorReporter.fatalTypeError(
|
||||||
|
typeName->location(),
|
||||||
|
"Library types cannot be used as mapping keys."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (typeName->annotation().type->category() != Type::Category::Enum)
|
||||||
|
m_errorReporter.fatalTypeError(
|
||||||
|
typeName->location(),
|
||||||
|
"Only elementary types, contract types or enums are allowed as mapping keys."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
solAssert(dynamic_cast<ElementaryTypeName const*>(&_mapping.keyType()), "");
|
||||||
|
|
||||||
|
TypePointer keyType = _mapping.keyType().annotation().type;
|
||||||
|
TypePointer valueType = _mapping.valueType().annotation().type;
|
||||||
|
|
||||||
// Convert key type to memory.
|
// Convert key type to memory.
|
||||||
keyType = TypeProvider::withLocationIfReference(DataLocation::Memory, keyType);
|
keyType = TypeProvider::withLocationIfReference(DataLocation::Memory, keyType);
|
||||||
|
|
||||||
// Convert value type to storage reference.
|
// Convert value type to storage reference.
|
||||||
valueType = TypeProvider::withLocationIfReference(DataLocation::Storage, valueType);
|
valueType = TypeProvider::withLocationIfReference(DataLocation::Storage, valueType);
|
||||||
_typeName.annotation().type = TypeProvider::mapping(keyType, valueType);
|
_mapping.annotation().type = TypeProvider::mapping(keyType, valueType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReferencesResolver::endVisit(ArrayTypeName const& _typeName)
|
void ReferencesResolver::endVisit(ArrayTypeName const& _typeName)
|
||||||
|
@ -81,7 +81,7 @@ private:
|
|||||||
void endVisit(ModifierDefinition const& _modifierDefinition) override;
|
void endVisit(ModifierDefinition const& _modifierDefinition) override;
|
||||||
void endVisit(UserDefinedTypeName const& _typeName) override;
|
void endVisit(UserDefinedTypeName const& _typeName) override;
|
||||||
void endVisit(FunctionTypeName const& _typeName) override;
|
void endVisit(FunctionTypeName const& _typeName) override;
|
||||||
void endVisit(Mapping const& _typeName) override;
|
void endVisit(Mapping const& _mapping) override;
|
||||||
void endVisit(ArrayTypeName const& _typeName) override;
|
void endVisit(ArrayTypeName const& _typeName) override;
|
||||||
bool visit(InlineAssembly const& _inlineAssembly) override;
|
bool visit(InlineAssembly const& _inlineAssembly) override;
|
||||||
bool visit(Return const& _return) override;
|
bool visit(Return const& _return) override;
|
||||||
|
@ -2876,30 +2876,6 @@ void TypeChecker::endVisit(Literal const& _literal)
|
|||||||
_literal.annotation().isPure = true;
|
_literal.annotation().isPure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeChecker::visit(Mapping const& _mapping)
|
|
||||||
{
|
|
||||||
if (auto const* keyType = dynamic_cast<UserDefinedTypeName const*>(&_mapping.keyType()))
|
|
||||||
{
|
|
||||||
if (auto const* contractType = dynamic_cast<ContractType const*>(keyType->annotation().type))
|
|
||||||
{
|
|
||||||
if (contractType->contractDefinition().isLibrary())
|
|
||||||
m_errorReporter.typeError(
|
|
||||||
keyType->location(),
|
|
||||||
"Library types cannot be used as mapping keys."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (keyType->annotation().type->category() != Type::Category::Enum)
|
|
||||||
m_errorReporter.typeError(
|
|
||||||
keyType->location(),
|
|
||||||
"Only elementary types, contract types or enums are allowed as mapping keys."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
solAssert(dynamic_cast<ElementaryTypeName const*>(&_mapping.keyType()), "");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool TypeChecker::contractDependenciesAreCyclic(
|
bool TypeChecker::contractDependenciesAreCyclic(
|
||||||
ContractDefinition const& _contract,
|
ContractDefinition const& _contract,
|
||||||
std::set<ContractDefinition const*> const& _seenContracts
|
std::set<ContractDefinition const*> const& _seenContracts
|
||||||
|
@ -143,7 +143,6 @@ private:
|
|||||||
bool visit(Identifier const& _identifier) override;
|
bool visit(Identifier const& _identifier) override;
|
||||||
void endVisit(ElementaryTypeNameExpression const& _expr) override;
|
void endVisit(ElementaryTypeNameExpression const& _expr) override;
|
||||||
void endVisit(Literal const& _literal) override;
|
void endVisit(Literal const& _literal) override;
|
||||||
bool visit(Mapping const& _mapping) override;
|
|
||||||
|
|
||||||
bool contractDependenciesAreCyclic(
|
bool contractDependenciesAreCyclic(
|
||||||
ContractDefinition const& _contract,
|
ContractDefinition const& _contract,
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
// Used to segfault.
|
||||||
|
contract C {
|
||||||
|
struct S {
|
||||||
|
mapping(S => uint) a;
|
||||||
|
}
|
||||||
|
function g (S calldata) external view {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (56-57): Only elementary types, contract types or enums are allowed as mapping keys.
|
Loading…
Reference in New Issue
Block a user