aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AST.cpp40
-rw-r--r--AST.h1
-rw-r--r--CompilerStack.cpp2
-rw-r--r--Parser.cpp5
4 files changed, 44 insertions, 4 deletions
diff --git a/AST.cpp b/AST.cpp
index 52c58170..2ada7362 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -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())
@@ -128,6 +130,42 @@ 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"));
+ // if (functions.count(name) && !functions[name] && function->isFullyImplemented())
+ // functions.insert(make_pair(name, true);
+
+ // if (functions.count(name) && !functions[name] && function->isFullyImplemented)
+ // functions.insert(make_pair(name, true));
+
+ // functions.insert(make_pair(name, function->isFullyImplemented()));
+ functions[name] = function->isFullyImplemented();
+
+ // if (function->isFullyImplemented())
+ // full_functions.insert(make_pair(name, function.get()));
+ // else
+ // abs_functions.insert(make_pair(name, function.get()));
+ }
+ }
+ 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
@@ -643,6 +681,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 object 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},
diff --git a/AST.h b/AST.h
index c1da90cd..8570e7bd 100644
--- a/AST.h
+++ b/AST.h
@@ -283,6 +283,7 @@ public:
private:
void checkIllegalOverrides() const;
+ void checkAbstractFunctions();
std::vector<std::pair<FixedHash<4>, FunctionTypePointer>> const& getInterfaceFunctionList() const;
diff --git a/CompilerStack.cpp b/CompilerStack.cpp
index 55ec0cb5..1301bfa5 100644
--- a/CompilerStack.cpp
+++ b/CompilerStack.cpp
@@ -138,6 +138,8 @@ void CompilerStack::compile(bool _optimize)
for (ASTPointer<ASTNode> const& node: source->ast->getNodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
{
+ if (!contract->isFullyImplemented())
+ continue;
shared_ptr<Compiler> compiler = make_shared<Compiler>(_optimize);
compiler->compileContract(*contract, contractBytecode);
Contract& compiledContract = m_contracts[contract->getName()];
diff --git a/Parser.cpp b/Parser.cpp
index 0f1b3406..5c7676df 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -141,10 +141,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
if (currentToken == Token::RBrace)
break;
else if (currentToken == Token::Function)
- {
- ASTPointer<FunctionDefinition> func = parseFunctionDefinition(name.get());
- functions.push_back(func);
- }
+ functions.push_back(parseFunctionDefinition(name.get()));
else if (currentToken == Token::Struct)
structs.push_back(parseStructDefinition());
else if (currentToken == Token::Enum)