aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/analysis/ContractLevelChecker.cpp
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-11-30 00:44:38 +0800
committerchriseth <chris@ethereum.org>2018-11-30 23:30:19 +0800
commit89cf6a5a38b02c3da1377279fcd98d690a58a978 (patch)
tree74ad1f5c2362a26d4a67bab229872311d3435ade /libsolidity/analysis/ContractLevelChecker.cpp
parentd054a3b85d70508611c4f8a1e093610ab95cfa37 (diff)
downloaddexon-solidity-89cf6a5a38b02c3da1377279fcd98d690a58a978.tar
dexon-solidity-89cf6a5a38b02c3da1377279fcd98d690a58a978.tar.gz
dexon-solidity-89cf6a5a38b02c3da1377279fcd98d690a58a978.tar.bz2
dexon-solidity-89cf6a5a38b02c3da1377279fcd98d690a58a978.tar.lz
dexon-solidity-89cf6a5a38b02c3da1377279fcd98d690a58a978.tar.xz
dexon-solidity-89cf6a5a38b02c3da1377279fcd98d690a58a978.tar.zst
dexon-solidity-89cf6a5a38b02c3da1377279fcd98d690a58a978.zip
Move override checks.
Diffstat (limited to 'libsolidity/analysis/ContractLevelChecker.cpp')
-rw-r--r--libsolidity/analysis/ContractLevelChecker.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp
index a2e76edf..bf132d63 100644
--- a/libsolidity/analysis/ContractLevelChecker.cpp
+++ b/libsolidity/analysis/ContractLevelChecker.cpp
@@ -35,6 +35,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract)
{
checkContractDuplicateFunctions(_contract);
checkContractDuplicateEvents(_contract);
+ checkContractIllegalOverrides(_contract);
return Error::containsOnlyWarnings(m_errorReporter.errors());
}
@@ -120,3 +121,85 @@ void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const
}
}
}
+
+void ContractLevelChecker::checkContractIllegalOverrides(ContractDefinition const& _contract)
+{
+ // TODO unify this at a later point. for this we need to put the constness and the access specifier
+ // into the types
+ map<string, vector<FunctionDefinition const*>> functions;
+ map<string, ModifierDefinition const*> modifiers;
+
+ // We search from derived to base, so the stored item causes the error.
+ for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
+ {
+ for (FunctionDefinition const* function: contract->definedFunctions())
+ {
+ if (function->isConstructor())
+ continue; // constructors can neither be overridden nor override anything
+ string const& name = function->name();
+ if (modifiers.count(name))
+ m_errorReporter.typeError(modifiers[name]->location(), "Override changes function to modifier.");
+
+ for (FunctionDefinition const* overriding: functions[name])
+ checkFunctionOverride(*overriding, *function);
+
+ functions[name].push_back(function);
+ }
+ for (ModifierDefinition const* modifier: contract->functionModifiers())
+ {
+ string const& name = modifier->name();
+ ModifierDefinition const*& override = modifiers[name];
+ if (!override)
+ override = modifier;
+ else if (ModifierType(*override) != ModifierType(*modifier))
+ m_errorReporter.typeError(override->location(), "Override changes modifier signature.");
+ if (!functions[name].empty())
+ m_errorReporter.typeError(override->location(), "Override changes modifier to function.");
+ }
+ }
+}
+
+void ContractLevelChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super)
+{
+ FunctionTypePointer functionType = FunctionType(_function).asCallableFunction(false);
+ FunctionTypePointer superType = FunctionType(_super).asCallableFunction(false);
+
+ if (!functionType->hasEqualParameterTypes(*superType))
+ return;
+ if (!functionType->hasEqualReturnTypes(*superType))
+ overrideError(_function, _super, "Overriding function return types differ.");
+
+ if (!_function.annotation().superFunction)
+ _function.annotation().superFunction = &_super;
+
+ if (_function.visibility() != _super.visibility())
+ {
+ // Visibility change from external to public is fine.
+ // Any other change is disallowed.
+ if (!(
+ _super.visibility() == FunctionDefinition::Visibility::External &&
+ _function.visibility() == FunctionDefinition::Visibility::Public
+ ))
+ overrideError(_function, _super, "Overriding function visibility differs.");
+ }
+ if (_function.stateMutability() != _super.stateMutability())
+ overrideError(
+ _function,
+ _super,
+ "Overriding function changes state mutability from \"" +
+ stateMutabilityToString(_super.stateMutability()) +
+ "\" to \"" +
+ stateMutabilityToString(_function.stateMutability()) +
+ "\"."
+ );
+}
+
+void ContractLevelChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message)
+{
+ m_errorReporter.typeError(
+ function.location(),
+ SecondarySourceLocation().append("Overridden function is here:", super.location()),
+ message
+ );
+}
+