diff options
author | chriseth <chris@ethereum.org> | 2018-11-30 00:44:38 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2018-11-30 23:30:19 +0800 |
commit | 89cf6a5a38b02c3da1377279fcd98d690a58a978 (patch) | |
tree | 74ad1f5c2362a26d4a67bab229872311d3435ade /libsolidity/analysis/ContractLevelChecker.cpp | |
parent | d054a3b85d70508611c4f8a1e093610ab95cfa37 (diff) | |
download | dexon-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.cpp | 83 |
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 + ); +} + |