mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
More strict override check for data locations.
This commit is contained in:
@@ -39,7 +39,7 @@ namespace
|
||||
{
|
||||
|
||||
template <class T, class B>
|
||||
bool hasEqualParameters(T const& _a, B const& _b)
|
||||
bool hasEqualExternalCallableParameters(T const& _a, B const& _b)
|
||||
{
|
||||
return FunctionType(_a).asExternallyCallableFunction(false)->hasEqualParameterTypes(
|
||||
*FunctionType(_b).asExternallyCallableFunction(false)
|
||||
@@ -204,7 +204,7 @@ void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const
|
||||
SecondarySourceLocation ssl;
|
||||
|
||||
for (size_t j = i + 1; j < overloads.size(); ++j)
|
||||
if (hasEqualParameters(*overloads[i], *overloads[j]))
|
||||
if (hasEqualExternalCallableParameters(*overloads[i], *overloads[j]))
|
||||
{
|
||||
solAssert(
|
||||
(
|
||||
|
||||
@@ -313,7 +313,7 @@ Token OverrideProxy::functionKind() const
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
FunctionType const* OverrideProxy::functionType() const
|
||||
FunctionType const* OverrideProxy::externalFunctionType() const
|
||||
{
|
||||
return std::visit(GenericVisitor{
|
||||
[&](FunctionDefinition const* _item) { return FunctionType(*_item).asExternallyCallableFunction(false); },
|
||||
@@ -322,6 +322,15 @@ FunctionType const* OverrideProxy::functionType() const
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
FunctionType const* OverrideProxy::originalFunctionType() const
|
||||
{
|
||||
return std::visit(GenericVisitor{
|
||||
[&](FunctionDefinition const* _item) { return TypeProvider::function(*_item); },
|
||||
[&](VariableDeclaration const*) -> FunctionType const* { solAssert(false, "Requested specific function type of variable."); return nullptr; },
|
||||
[&](ModifierDefinition const*) -> FunctionType const* { solAssert(false, "Requested specific function type of modifier."); return nullptr; }
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
ModifierType const* OverrideProxy::modifierType() const
|
||||
{
|
||||
return std::visit(GenericVisitor{
|
||||
@@ -413,7 +422,7 @@ OverrideProxy::OverrideComparator const& OverrideProxy::overrideComparator() con
|
||||
[&](FunctionDefinition const* _function)
|
||||
{
|
||||
vector<string> paramTypes;
|
||||
for (Type const* t: functionType()->parameterTypes())
|
||||
for (Type const* t: externalFunctionType()->parameterTypes())
|
||||
paramTypes.emplace_back(t->richIdentifier());
|
||||
return OverrideComparator{
|
||||
_function->name(),
|
||||
@@ -424,7 +433,7 @@ OverrideProxy::OverrideComparator const& OverrideProxy::overrideComparator() con
|
||||
[&](VariableDeclaration const* _var)
|
||||
{
|
||||
vector<string> paramTypes;
|
||||
for (Type const* t: functionType()->parameterTypes())
|
||||
for (Type const* t: externalFunctionType()->parameterTypes())
|
||||
paramTypes.emplace_back(t->richIdentifier());
|
||||
return OverrideComparator{
|
||||
_var->name(),
|
||||
@@ -589,14 +598,17 @@ void OverrideChecker::checkOverride(OverrideProxy const& _overriding, OverridePr
|
||||
|
||||
if (_super.isFunction())
|
||||
{
|
||||
FunctionType const* functionType = _overriding.functionType();
|
||||
FunctionType const* superType = _super.functionType();
|
||||
FunctionType const* functionType = _overriding.externalFunctionType();
|
||||
FunctionType const* superType = _super.externalFunctionType();
|
||||
|
||||
bool returnTypesDifferAlready = false;
|
||||
if (_overriding.functionKind() != Token::Fallback)
|
||||
{
|
||||
solAssert(functionType->hasEqualParameterTypes(*superType), "Override doesn't have equal parameters!");
|
||||
|
||||
if (!functionType->hasEqualReturnTypes(*superType))
|
||||
{
|
||||
returnTypesDifferAlready = true;
|
||||
overrideError(
|
||||
_overriding,
|
||||
_super,
|
||||
@@ -604,6 +616,36 @@ void OverrideChecker::checkOverride(OverrideProxy const& _overriding, OverridePr
|
||||
"Overriding " + _overriding.astNodeName() + " return types differ.",
|
||||
"Overridden " + _overriding.astNodeName() + " is here:"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// The override proxy considers calldata and memory the same data location.
|
||||
// Here we do a more specific check:
|
||||
// Data locations of parameters and return variables have to match
|
||||
// unless we have a public function overriding an external one.
|
||||
if (
|
||||
_overriding.isFunction() &&
|
||||
!returnTypesDifferAlready &&
|
||||
_super.visibility() != Visibility::External &&
|
||||
_overriding.functionKind() != Token::Fallback
|
||||
)
|
||||
{
|
||||
if (!_overriding.originalFunctionType()->hasEqualParameterTypes(*_super.originalFunctionType()))
|
||||
overrideError(
|
||||
_overriding,
|
||||
_super,
|
||||
7723_error,
|
||||
"Data locations of parameters have to be the same when overriding non-external functions, but they differ.",
|
||||
"Overridden " + _overriding.astNodeName() + " is here:"
|
||||
);
|
||||
if (!_overriding.originalFunctionType()->hasEqualReturnTypes(*_super.originalFunctionType()))
|
||||
overrideError(
|
||||
_overriding,
|
||||
_super,
|
||||
1443_error,
|
||||
"Data locations of return variables have to be the same when overriding non-external functions, but they differ.",
|
||||
"Overridden " + _overriding.astNodeName() + " is here:"
|
||||
);
|
||||
}
|
||||
|
||||
// Stricter mutability is always okay except when super is Payable
|
||||
|
||||
@@ -84,7 +84,10 @@ public:
|
||||
/// @returns receive / fallback / function (only the latter for modifiers and variables);
|
||||
langutil::Token functionKind() const;
|
||||
|
||||
FunctionType const* functionType() const;
|
||||
/// @returns the externally callable function type
|
||||
FunctionType const* externalFunctionType() const;
|
||||
/// @returns the (unmodified) function type
|
||||
FunctionType const* originalFunctionType() const;
|
||||
ModifierType const* modifierType() const;
|
||||
|
||||
Declaration const* declaration() const;
|
||||
@@ -101,6 +104,7 @@ public:
|
||||
|
||||
/**
|
||||
* Struct to help comparing override items about whether they override each other.
|
||||
* Compares functions based on their "externally callable" type.
|
||||
* Does not produce a total order.
|
||||
*/
|
||||
struct OverrideComparator
|
||||
|
||||
Reference in New Issue
Block a user