diff options
author | chriseth <c@ethdev.com> | 2015-03-31 01:33:30 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-03-31 01:33:30 +0800 |
commit | eab085baf6d9953c008803b1d27e0076d51441a5 (patch) | |
tree | 5148b9e0f2ddeb880b689f9ebe944f46c5801bb5 /AST.cpp | |
parent | f728a336b1af6ae25b5cb5282119bef8f55c08b6 (diff) | |
parent | c6781ed38dd7c634ef8dbbbebcac582451c04ddd (diff) | |
download | dexon-solidity-eab085baf6d9953c008803b1d27e0076d51441a5.tar.gz dexon-solidity-eab085baf6d9953c008803b1d27e0076d51441a5.tar.zst dexon-solidity-eab085baf6d9953c008803b1d27e0076d51441a5.zip |
Merge pull request #1414 from LefterisJP/sol_notImplementedFuncs
Interface contracts
Diffstat (limited to 'AST.cpp')
-rw-r--r-- | AST.cpp | 34 |
1 files changed, 32 insertions, 2 deletions
@@ -21,6 +21,7 @@ */ #include <algorithm> +#include <boost/range/adaptor/reversed.hpp> #include <libsolidity/Utils.h> #include <libsolidity/AST.h> #include <libsolidity/ASTVisitor.h> @@ -52,6 +53,7 @@ void ContractDefinition::checkTypeRequirements() baseSpecifier->checkTypeRequirements(); checkIllegalOverrides(); + checkAbstractFunctions(); FunctionDefinition const* constructor = getConstructor(); if (constructor && !constructor->getReturnParameters().empty()) @@ -60,6 +62,7 @@ void ContractDefinition::checkTypeRequirements() FunctionDefinition const* fallbackFunction = nullptr; for (ASTPointer<FunctionDefinition> const& function: getDefinedFunctions()) + { if (function->getName().empty()) { if (fallbackFunction) @@ -71,6 +74,9 @@ void ContractDefinition::checkTypeRequirements() BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError("Fallback function cannot take parameters.")); } } + if (!function->isFullyImplemented()) + setFullyImplemented(false); + } for (ASTPointer<ModifierDefinition> const& modifier: getFunctionModifiers()) modifier->checkTypeRequirements(); @@ -124,6 +130,28 @@ FunctionDefinition const* ContractDefinition::getFallbackFunction() const return nullptr; } +void ContractDefinition::checkAbstractFunctions() +{ + map<string, bool> functions; + + // Search from base to derived + for (ContractDefinition const* contract: boost::adaptors::reverse(getLinearizedBaseContracts())) + for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions()) + { + string const& name = function->getName(); + if (!function->isFullyImplemented() && functions.count(name) && functions[name]) + BOOST_THROW_EXCEPTION(function->createTypeError("Redeclaring an already implemented function as abstract")); + functions[name] = function->isFullyImplemented(); + } + + for (auto const& it: functions) + if (!it.second) + { + setFullyImplemented(false); + break; + } +} + void ContractDefinition::checkIllegalOverrides() const { // TODO unify this at a later point. for this we need to put the constness and the access specifier @@ -316,8 +344,8 @@ void FunctionDefinition::checkTypeRequirements() modifier->checkTypeRequirements(isConstructor() ? dynamic_cast<ContractDefinition const&>(*getScope()).getBaseContracts() : vector<ASTPointer<InheritanceSpecifier>>()); - - m_body->checkTypeRequirements(); + if (m_body) + m_body->checkTypeRequirements(); } string FunctionDefinition::externalSignature() const @@ -649,6 +677,8 @@ void NewExpression::checkTypeRequirements() m_contract = dynamic_cast<ContractDefinition const*>(m_contractName->getReferencedDeclaration()); if (!m_contract) BOOST_THROW_EXCEPTION(createTypeError("Identifier is not a contract.")); + if (!m_contract->isFullyImplemented()) + BOOST_THROW_EXCEPTION(m_contract->createTypeError("Trying to create an instance of an abstract contract.")); shared_ptr<ContractType const> contractType = make_shared<ContractType>(*m_contract); TypePointers const& parameterTypes = contractType->getConstructorType()->getParameterTypes(); m_type = make_shared<FunctionType>(parameterTypes, TypePointers{contractType}, |