From c835bcec623d6b6166add70456f5b6bee5c90572 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 10 Jul 2017 10:47:12 +0100 Subject: [PATCH] Replace isFullyImplemented with unimplementedFunctions in ASTAnnotations --- libsolidity/analysis/TypeChecker.cpp | 19 +++++++++---------- libsolidity/ast/ASTAnnotations.h | 5 +++-- libsolidity/ast/ASTJsonConverter.cpp | 2 +- libsolidity/interface/CompilerStack.cpp | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 5fe03aa66..fab410ebd 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -113,7 +113,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract) } } if (!function->isImplemented()) - _contract.annotation().isFullyImplemented = false; + _contract.annotation().unimplementedFunctions.push_back(function); } for (auto const& n: _contract.subNodes()) @@ -188,7 +188,6 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont using FunTypeAndFlag = std::pair; map> functions; - bool allBaseConstructorsImplemented = true; // Search from base to derived for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts)) for (FunctionDefinition const* function: contract->definedFunctions()) @@ -199,7 +198,7 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont if (!function->isImplemented()) // Base contract's constructor is not fully implemented, no way to get // out of this. - allBaseConstructorsImplemented = false; + _contract.annotation().unimplementedFunctions.push_back(function); continue; } auto& overloads = functions[function->name()]; @@ -219,16 +218,15 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont it->second = true; } - if (!allBaseConstructorsImplemented) - _contract.annotation().isFullyImplemented = false; - // Set to not fully implemented if at least one flag is false. for (auto const& it: functions) for (auto const& funAndFlag: it.second) if (!funAndFlag.second) { - _contract.annotation().isFullyImplemented = false; - return; + FunctionDefinition const* function = dynamic_cast(&funAndFlag.first->declaration()); + solAssert(function, ""); + _contract.annotation().unimplementedFunctions.push_back(function); + break; } } @@ -266,7 +264,8 @@ void TypeChecker::checkContractAbstractConstructors(ContractDefinition const& _c } } if (!argumentsNeeded.empty()) - _contract.annotation().isFullyImplemented = false; + for (ContractDefinition const* contract: argumentsNeeded) + _contract.annotation().unimplementedFunctions.push_back(contract->constructor()); } void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contract) @@ -1523,7 +1522,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression) if (!contract) m_errorReporter.fatalTypeError(_newExpression.location(), "Identifier is not a contract."); - if (!contract->annotation().isFullyImplemented) + if (!contract->annotation().unimplementedFunctions.empty()) m_errorReporter.typeError(_newExpression.location(), "Trying to create an instance of an abstract contract."); if (!contract->constructorIsPublic()) m_errorReporter.typeError(_newExpression.location(), "Contract with internal constructor cannot be created directly."); diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 45a6dd1a4..ecddbe21b 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -79,8 +79,9 @@ struct TypeDeclarationAnnotation: ASTAnnotation struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, DocumentedAnnotation { - /// Whether all functions are implemented. - bool isFullyImplemented = true; + /// List of functions without a body. Can also contain functions from base classes, + /// especially constructors. + std::vector unimplementedFunctions; /// List of all (direct and indirect) base contracts in order from derived to /// base, including the contract itself. std::vector linearizedBaseContracts; diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index eda70b63e..e4a602cba 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -253,7 +253,7 @@ bool ASTJsonConverter::visit(ContractDefinition const& _node) make_pair("name", _node.name()), make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue), make_pair("contractKind", contractKind(_node.contractKind())), - make_pair("fullyImplemented", _node.annotation().isFullyImplemented), + make_pair("fullyImplemented", _node.annotation().unimplementedFunctions.empty()), make_pair("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts)), make_pair("baseContracts", toJson(_node.baseContracts())), make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies)), diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 9689b700c..7c66a8430 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -639,7 +639,7 @@ void CompilerStack::compileContract( { if ( _compiledContracts.count(&_contract) || - !_contract.annotation().isFullyImplemented || + !_contract.annotation().unimplementedFunctions.empty() || !_contract.constructorIsPublic() ) return;