Browse Source

Check all constructors in inheritance chain get args

- Also add a missing override in a function of EnumValue
cl-refactor
Lefteris Karapetsas 10 years ago
parent
commit
2279e40274
  1. 42
      libsolidity/AST.cpp
  2. 3
      libsolidity/AST.h
  3. 19
      test/SolidityNameAndTypeResolution.cpp

42
libsolidity/AST.cpp

@ -54,6 +54,7 @@ void ContractDefinition::checkTypeRequirements()
checkIllegalOverrides();
checkAbstractFunctions();
checkAbstractConstructors();
FunctionDefinition const* constructor = getConstructor();
if (constructor && !constructor->getReturnParameters().empty())
@ -152,6 +153,47 @@ void ContractDefinition::checkAbstractFunctions()
}
}
void ContractDefinition::checkAbstractConstructors()
{
set<FunctionDefinition const*> argumentsNeeded;
set<FunctionDefinition const*> argumentsProvided;
// check that we get arguments for all base constructors that need it.
// If not mark the contract as abstract (not fully implemented)
vector<ContractDefinition const*> const& bases = getLinearizedBaseContracts();
for (ContractDefinition const* contract: bases)
{
FunctionDefinition const* constructor = contract->getConstructor();
if (constructor)
{
if (!constructor->getParameters().empty())
argumentsProvided.insert(constructor);
for (auto const& modifier: constructor->getModifiers())
{
auto baseContract = dynamic_cast<ContractDefinition const*>(
modifier->getName()->getReferencedDeclaration());
if (baseContract)
{
FunctionDefinition const* baseConstructor = baseContract->getConstructor();
if (argumentsProvided.count(baseConstructor) == 1)
argumentsNeeded.insert(baseConstructor);
}
}
}
for (ASTPointer<InheritanceSpecifier> const& base: contract->getBaseContracts())
{
ContractDefinition const* baseContract = dynamic_cast<ContractDefinition const*>(
base->getName()->getReferencedDeclaration());
solAssert(baseContract, "");
FunctionDefinition const* baseConstructor = baseContract->getConstructor();
if (argumentsProvided.count(baseConstructor) == 1)
argumentsNeeded.insert(baseConstructor);
}
}
if (argumentsProvided != argumentsNeeded)
setFullyImplemented(false);
}
void ContractDefinition::checkIllegalOverrides() const
{
// TODO unify this at a later point. for this we need to put the constness and the access specifier

3
libsolidity/AST.h

@ -284,6 +284,7 @@ public:
private:
void checkIllegalOverrides() const;
void checkAbstractFunctions();
void checkAbstractConstructors();
std::vector<std::pair<FixedHash<4>, FunctionTypePointer>> const& getInterfaceFunctionList() const;
@ -376,7 +377,7 @@ class EnumValue: public Declaration
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
TypePointer getType(ContractDefinition const* = nullptr) const;
TypePointer getType(ContractDefinition const* = nullptr) const override;
};
/**

19
test/SolidityNameAndTypeResolution.cpp

@ -421,6 +421,25 @@ BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional)
ETH_TEST_REQUIRE_NO_THROW(parseTextAndResolveNames(text), "Parsing and name resolving failed");
}
BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_not_provided)
{
ASTPointer<SourceUnit> sourceUnit;
char const* text = R"(
contract BaseBase { function BaseBase(uint j); }
contract base is BaseBase { function foo(); }
contract derived is base {
function derived(uint i) {}
function foo() {}
}
)";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->getNodes();
BOOST_CHECK_EQUAL(nodes.size(), 3);
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
BOOST_CHECK(derived);
BOOST_CHECK(!derived->isFullyImplemented());
}
BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract)
{
ASTPointer<SourceUnit> sourceUnit;

Loading…
Cancel
Save