Browse Source

Merge pull request #2269 from chriseth/sol_fix_abstractCheck

Fixed checking of abstract functions.
cl-refactor
chriseth 10 years ago
parent
commit
80901ecf19
  1. 36
      libsolidity/AST.cpp
  2. 17
      test/libsolidity/SolidityNameAndTypeResolution.cpp

36
libsolidity/AST.cpp

@ -175,24 +175,40 @@ void ContractDefinition::checkDuplicateFunctions() const
void ContractDefinition::checkAbstractFunctions() void ContractDefinition::checkAbstractFunctions()
{ {
map<string, bool> functions; // Mapping from name to function definition (exactly one per argument type equality class) and
// flag to indicate whether it is fully implemented.
using FunTypeAndFlag = std::pair<FunctionTypePointer, bool>;
map<string, vector<FunTypeAndFlag>> functions;
// Search from base to derived // Search from base to derived
for (ContractDefinition const* contract: boost::adaptors::reverse(getLinearizedBaseContracts())) for (ContractDefinition const* contract: boost::adaptors::reverse(getLinearizedBaseContracts()))
for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions()) for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions())
{ {
string const& name = function->getName(); auto& overloads = functions[function->getName()];
if (!function->isFullyImplemented() && functions.count(name) && functions[name]) FunctionTypePointer funType = make_shared<FunctionType>(*function);
BOOST_THROW_EXCEPTION(function->createTypeError("Redeclaring an already implemented function as abstract")); auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag)
functions[name] = function->isFullyImplemented(); {
return funType->hasEqualArgumentTypes(*_funAndFlag.first);
});
if (it == overloads.end())
overloads.push_back(make_pair(funType, function->isFullyImplemented()));
else if (it->second)
{
if (!function->isFullyImplemented())
BOOST_THROW_EXCEPTION(function->createTypeError("Redeclaring an already implemented function as abstract"));
}
else if (function->isFullyImplemented())
it->second = true;
} }
// Set to not fully implemented if at least one flag is false.
for (auto const& it: functions) for (auto const& it: functions)
if (!it.second) for (auto const& funAndFlag: it.second)
{ if (!funAndFlag.second)
setFullyImplemented(false); {
break; setFullyImplemented(false);
} return;
}
} }
void ContractDefinition::checkAbstractConstructors() void ContractDefinition::checkAbstractConstructors()

17
test/libsolidity/SolidityNameAndTypeResolution.cpp

@ -403,6 +403,23 @@ BOOST_AUTO_TEST_CASE(abstract_contract)
BOOST_CHECK(derived->getDefinedFunctions()[0]->isFullyImplemented()); BOOST_CHECK(derived->getDefinedFunctions()[0]->isFullyImplemented());
} }
BOOST_AUTO_TEST_CASE(abstract_contract_with_overload)
{
ASTPointer<SourceUnit> sourceUnit;
char const* text = R"(
contract base { function foo(bool); }
contract derived is base { function foo(uint) {} }
)";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->getNodes();
ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[0].get());
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[1].get());
BOOST_REQUIRE(base);
BOOST_CHECK(!base->isFullyImplemented());
BOOST_REQUIRE(derived);
BOOST_CHECK(!derived->isFullyImplemented());
}
BOOST_AUTO_TEST_CASE(create_abstract_contract) BOOST_AUTO_TEST_CASE(create_abstract_contract)
{ {
ASTPointer<SourceUnit> sourceUnit; ASTPointer<SourceUnit> sourceUnit;

Loading…
Cancel
Save