@ -21,6 +21,7 @@
*/
*/
# include <algorithm>
# include <algorithm>
# include <boost/range/adaptor/reversed.hpp>
# include <libsolidity/Utils.h>
# include <libsolidity/Utils.h>
# include <libsolidity/AST.h>
# include <libsolidity/AST.h>
# include <libsolidity/ASTVisitor.h>
# include <libsolidity/ASTVisitor.h>
@ -52,6 +53,7 @@ void ContractDefinition::checkTypeRequirements()
baseSpecifier - > checkTypeRequirements ( ) ;
baseSpecifier - > checkTypeRequirements ( ) ;
checkIllegalOverrides ( ) ;
checkIllegalOverrides ( ) ;
checkAbstractFunctions ( ) ;
FunctionDefinition const * constructor = getConstructor ( ) ;
FunctionDefinition const * constructor = getConstructor ( ) ;
if ( constructor & & ! constructor - > getReturnParameters ( ) . empty ( ) )
if ( constructor & & ! constructor - > getReturnParameters ( ) . empty ( ) )
@ -128,6 +130,42 @@ FunctionDefinition const* ContractDefinition::getFallbackFunction() const
return nullptr ;
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
void ContractDefinition : : checkIllegalOverrides ( ) const
{
{
// TODO unify this at a later point. for this we need to put the constness and the access specifier
// 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 ( ) ) ;
m_contract = dynamic_cast < ContractDefinition const * > ( m_contractName - > getReferencedDeclaration ( ) ) ;
if ( ! m_contract )
if ( ! m_contract )
BOOST_THROW_EXCEPTION ( createTypeError ( " Identifier is not a 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 ) ;
shared_ptr < ContractType const > contractType = make_shared < ContractType > ( * m_contract ) ;
TypePointers const & parameterTypes = contractType - > getConstructorType ( ) - > getParameterTypes ( ) ;
TypePointers const & parameterTypes = contractType - > getConstructorType ( ) - > getParameterTypes ( ) ;
m_type = make_shared < FunctionType > ( parameterTypes , TypePointers { contractType } ,
m_type = make_shared < FunctionType > ( parameterTypes , TypePointers { contractType } ,