mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1811 from ethereum/unimplementedConstructors
Contract inheriting from base with unimplemented constructor is abstract.
This commit is contained in:
commit
d626876310
@ -3,6 +3,9 @@
|
|||||||
Features:
|
Features:
|
||||||
* Support ``interface`` contracts.
|
* Support ``interface`` contracts.
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* Type system: Contract inheriting from base with unimplemented constructor should be abstract.
|
||||||
|
|
||||||
### 0.4.10 (2017-03-15)
|
### 0.4.10 (2017-03-15)
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
@ -187,13 +187,20 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont
|
|||||||
using FunTypeAndFlag = std::pair<FunctionTypePointer, bool>;
|
using FunTypeAndFlag = std::pair<FunctionTypePointer, bool>;
|
||||||
map<string, vector<FunTypeAndFlag>> functions;
|
map<string, vector<FunTypeAndFlag>> functions;
|
||||||
|
|
||||||
|
bool allBaseConstructorsImplemented = true;
|
||||||
// Search from base to derived
|
// Search from base to derived
|
||||||
for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts))
|
for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts))
|
||||||
for (FunctionDefinition const* function: contract->definedFunctions())
|
for (FunctionDefinition const* function: contract->definedFunctions())
|
||||||
{
|
{
|
||||||
// Take constructors out of overload hierarchy
|
// Take constructors out of overload hierarchy
|
||||||
if (function->isConstructor())
|
if (function->isConstructor())
|
||||||
|
{
|
||||||
|
if (!function->isImplemented())
|
||||||
|
// Base contract's constructor is not fully implemented, no way to get
|
||||||
|
// out of this.
|
||||||
|
allBaseConstructorsImplemented = false;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
auto& overloads = functions[function->name()];
|
auto& overloads = functions[function->name()];
|
||||||
FunctionTypePointer funType = make_shared<FunctionType>(*function);
|
FunctionTypePointer funType = make_shared<FunctionType>(*function);
|
||||||
auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag)
|
auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag)
|
||||||
@ -211,6 +218,9 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont
|
|||||||
it->second = true;
|
it->second = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!allBaseConstructorsImplemented)
|
||||||
|
_contract.annotation().isFullyImplemented = false;
|
||||||
|
|
||||||
// Set to not fully implemented if at least one flag is false.
|
// Set to not fully implemented if at least one flag is false.
|
||||||
for (auto const& it: functions)
|
for (auto const& it: functions)
|
||||||
for (auto const& funAndFlag: it.second)
|
for (auto const& funAndFlag: it.second)
|
||||||
|
@ -624,7 +624,12 @@ BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional)
|
|||||||
function foo() {}
|
function foo() {}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
ETH_TEST_REQUIRE_NO_THROW(parseAndAnalyse(text), "Parsing and name resolving failed");
|
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name resolving failed");
|
||||||
|
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
|
||||||
|
BOOST_CHECK_EQUAL(nodes.size(), 4);
|
||||||
|
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[3].get());
|
||||||
|
BOOST_REQUIRE(derived);
|
||||||
|
BOOST_CHECK(!derived->annotation().isFullyImplemented);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_not_provided)
|
BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_not_provided)
|
||||||
|
Loading…
Reference in New Issue
Block a user