mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'ethereum/develop' into sol_overloadingFunctions
Conflicts: libsolidity/AST.cpp libsolidity/AST.h
This commit is contained in:
commit
7a467bbf07
56
AST.cpp
56
AST.cpp
@ -55,6 +55,7 @@ void ContractDefinition::checkTypeRequirements()
|
|||||||
checkDuplicateFunctions();
|
checkDuplicateFunctions();
|
||||||
checkIllegalOverrides();
|
checkIllegalOverrides();
|
||||||
checkAbstractFunctions();
|
checkAbstractFunctions();
|
||||||
|
checkAbstractConstructors();
|
||||||
|
|
||||||
FunctionDefinition const* constructor = getConstructor();
|
FunctionDefinition const* constructor = getConstructor();
|
||||||
if (constructor && !constructor->getReturnParameters().empty())
|
if (constructor && !constructor->getReturnParameters().empty())
|
||||||
@ -181,6 +182,45 @@ void ContractDefinition::checkAbstractFunctions()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContractDefinition::checkAbstractConstructors()
|
||||||
|
{
|
||||||
|
set<ContractDefinition const*> argumentsNeeded;
|
||||||
|
// 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)
|
||||||
|
if (FunctionDefinition const* constructor = contract->getConstructor())
|
||||||
|
if (contract != this && !constructor->getParameters().empty())
|
||||||
|
argumentsNeeded.insert(contract);
|
||||||
|
|
||||||
|
for (ContractDefinition const* contract: bases)
|
||||||
|
{
|
||||||
|
if (FunctionDefinition const* constructor = contract->getConstructor())
|
||||||
|
for (auto const& modifier: constructor->getModifiers())
|
||||||
|
{
|
||||||
|
auto baseContract = dynamic_cast<ContractDefinition const*>(
|
||||||
|
&modifier->getName()->getReferencedDeclaration()
|
||||||
|
);
|
||||||
|
if (baseContract)
|
||||||
|
argumentsNeeded.erase(baseContract);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (ASTPointer<InheritanceSpecifier> const& base: contract->getBaseContracts())
|
||||||
|
{
|
||||||
|
auto baseContract = dynamic_cast<ContractDefinition const*>(
|
||||||
|
&base->getName()->getReferencedDeclaration()
|
||||||
|
);
|
||||||
|
solAssert(baseContract, "");
|
||||||
|
if (!base->getArguments().empty())
|
||||||
|
argumentsNeeded.erase(baseContract);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!argumentsNeeded.empty())
|
||||||
|
setFullyImplemented(false);
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -354,7 +394,7 @@ void InheritanceSpecifier::checkTypeRequirements()
|
|||||||
ContractDefinition const* base = dynamic_cast<ContractDefinition const*>(&m_baseName->getReferencedDeclaration());
|
ContractDefinition const* base = dynamic_cast<ContractDefinition const*>(&m_baseName->getReferencedDeclaration());
|
||||||
solAssert(base, "Base contract not available.");
|
solAssert(base, "Base contract not available.");
|
||||||
TypePointers parameterTypes = ContractType(*base).getConstructorType()->getParameterTypes();
|
TypePointers parameterTypes = ContractType(*base).getConstructorType()->getParameterTypes();
|
||||||
if (parameterTypes.size() != m_arguments.size())
|
if (!m_arguments.empty() && parameterTypes.size() != m_arguments.size())
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for constructor call."));
|
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for constructor call."));
|
||||||
for (size_t i = 0; i < m_arguments.size(); ++i)
|
for (size_t i = 0; i < m_arguments.size(); ++i)
|
||||||
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
|
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
|
||||||
@ -421,8 +461,8 @@ void FunctionDefinition::checkTypeRequirements()
|
|||||||
}
|
}
|
||||||
for (ASTPointer<ModifierInvocation> const& modifier: m_functionModifiers)
|
for (ASTPointer<ModifierInvocation> const& modifier: m_functionModifiers)
|
||||||
modifier->checkTypeRequirements(isConstructor() ?
|
modifier->checkTypeRequirements(isConstructor() ?
|
||||||
dynamic_cast<ContractDefinition const&>(*getScope()).getBaseContracts() :
|
dynamic_cast<ContractDefinition const&>(*getScope()).getLinearizedBaseContracts() :
|
||||||
vector<ASTPointer<InheritanceSpecifier>>());
|
vector<ContractDefinition const*>());
|
||||||
if (m_body)
|
if (m_body)
|
||||||
m_body->checkTypeRequirements();
|
m_body->checkTypeRequirements();
|
||||||
}
|
}
|
||||||
@ -500,7 +540,7 @@ void ModifierDefinition::checkTypeRequirements()
|
|||||||
m_body->checkTypeRequirements();
|
m_body->checkTypeRequirements();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModifierInvocation::checkTypeRequirements(vector<ASTPointer<InheritanceSpecifier>> const& _bases)
|
void ModifierInvocation::checkTypeRequirements(vector<ContractDefinition const*> const& _bases)
|
||||||
{
|
{
|
||||||
TypePointers argumentTypes;
|
TypePointers argumentTypes;
|
||||||
for (ASTPointer<Expression> const& argument: m_arguments)
|
for (ASTPointer<Expression> const& argument: m_arguments)
|
||||||
@ -517,10 +557,10 @@ void ModifierInvocation::checkTypeRequirements(vector<ASTPointer<InheritanceSpec
|
|||||||
parameters = &modifier->getParameters();
|
parameters = &modifier->getParameters();
|
||||||
else
|
else
|
||||||
// check parameters for Base constructors
|
// check parameters for Base constructors
|
||||||
for (auto const& base: _bases)
|
for (ContractDefinition const* base: _bases)
|
||||||
if (declaration == &base->getName()->getReferencedDeclaration())
|
if (declaration == base)
|
||||||
{
|
{
|
||||||
if (auto referencedConstructor = dynamic_cast<ContractDefinition const&>(*declaration).getConstructor())
|
if (auto referencedConstructor = base->getConstructor())
|
||||||
parameters = &referencedConstructor->getParameters();
|
parameters = &referencedConstructor->getParameters();
|
||||||
else
|
else
|
||||||
parameters = &emptyParameterList;
|
parameters = &emptyParameterList;
|
||||||
@ -777,7 +817,7 @@ void NewExpression::checkTypeRequirements(TypePointers const*)
|
|||||||
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())
|
if (!m_contract->isFullyImplemented())
|
||||||
BOOST_THROW_EXCEPTION(m_contract->createTypeError("Trying to create an instance of an abstract contract."));
|
BOOST_THROW_EXCEPTION(createTypeError("Trying to create an instance 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},
|
||||||
|
5
AST.h
5
AST.h
@ -287,6 +287,7 @@ private:
|
|||||||
void checkDuplicateFunctions() const;
|
void checkDuplicateFunctions() const;
|
||||||
void checkIllegalOverrides() const;
|
void checkIllegalOverrides() const;
|
||||||
void checkAbstractFunctions();
|
void checkAbstractFunctions();
|
||||||
|
void checkAbstractConstructors();
|
||||||
/// Checks that different functions with external visibility end up having different
|
/// Checks that different functions with external visibility end up having different
|
||||||
/// external argument types (i.e. different signature).
|
/// external argument types (i.e. different signature).
|
||||||
void checkExternalTypeClashes() const;
|
void checkExternalTypeClashes() const;
|
||||||
@ -382,7 +383,7 @@ class EnumValue: public Declaration
|
|||||||
|
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual void accept(ASTConstVisitor& _visitor) const override;
|
virtual void accept(ASTConstVisitor& _visitor) const override;
|
||||||
TypePointer getType(ContractDefinition const* = nullptr) const;
|
virtual TypePointer getType(ContractDefinition const* = nullptr) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -572,7 +573,7 @@ public:
|
|||||||
std::vector<ASTPointer<Expression>> const& getArguments() const { return m_arguments; }
|
std::vector<ASTPointer<Expression>> const& getArguments() const { return m_arguments; }
|
||||||
|
|
||||||
/// @param _bases is the list of base contracts for base constructor calls. For modifiers an empty vector should be passed.
|
/// @param _bases is the list of base contracts for base constructor calls. For modifiers an empty vector should be passed.
|
||||||
void checkTypeRequirements(std::vector<ASTPointer<InheritanceSpecifier>> const& _bases);
|
void checkTypeRequirements(std::vector<ContractDefinition const*> const& _bases);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTPointer<Identifier> m_modifierName;
|
ASTPointer<Identifier> m_modifierName;
|
||||||
|
@ -136,6 +136,7 @@ void Compiler::appendBaseConstructor(FunctionDefinition const& _constructor)
|
|||||||
FunctionType constructorType(_constructor);
|
FunctionType constructorType(_constructor);
|
||||||
if (!constructorType.getParameterTypes().empty())
|
if (!constructorType.getParameterTypes().empty())
|
||||||
{
|
{
|
||||||
|
solAssert(m_baseArguments.count(&_constructor), "");
|
||||||
std::vector<ASTPointer<Expression>> const* arguments = m_baseArguments[&_constructor];
|
std::vector<ASTPointer<Expression>> const* arguments = m_baseArguments[&_constructor];
|
||||||
solAssert(arguments, "");
|
solAssert(arguments, "");
|
||||||
for (unsigned i = 0; i < arguments->size(); ++i)
|
for (unsigned i = 0; i < arguments->size(); ++i)
|
||||||
|
@ -42,9 +42,10 @@ public:
|
|||||||
bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); }
|
bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); }
|
||||||
bytes getRuntimeBytecode() { return m_runtimeContext.getAssembledBytecode(m_optimize);}
|
bytes getRuntimeBytecode() { return m_runtimeContext.getAssembledBytecode(m_optimize);}
|
||||||
/// @arg _sourceCodes is the map of input files to source code strings
|
/// @arg _sourceCodes is the map of input files to source code strings
|
||||||
void streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap()) const
|
/// @arg _inJsonFromat shows whether the out should be in Json format
|
||||||
|
void streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap(), bool _inJsonFormat = false) const
|
||||||
{
|
{
|
||||||
m_context.streamAssembly(_stream, _sourceCodes);
|
m_context.streamAssembly(_stream, _sourceCodes, _inJsonFormat);
|
||||||
}
|
}
|
||||||
/// @returns Assembly items of the normal compiler context
|
/// @returns Assembly items of the normal compiler context
|
||||||
eth::AssemblyItems const& getAssemblyItems() const { return m_context.getAssembly().getItems(); }
|
eth::AssemblyItems const& getAssemblyItems() const { return m_context.getAssembly().getItems(); }
|
||||||
|
@ -122,7 +122,11 @@ public:
|
|||||||
|
|
||||||
eth::Assembly const& getAssembly() const { return m_asm; }
|
eth::Assembly const& getAssembly() const { return m_asm; }
|
||||||
/// @arg _sourceCodes is the map of input files to source code strings
|
/// @arg _sourceCodes is the map of input files to source code strings
|
||||||
void streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap()) const { m_asm.stream(_stream, "", _sourceCodes); }
|
/// @arg _inJsonFormat shows whether the out should be in Json format
|
||||||
|
void streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap(), bool _inJsonFormat = false) const
|
||||||
|
{
|
||||||
|
m_asm.stream(_stream, "", _sourceCodes, _inJsonFormat);
|
||||||
|
}
|
||||||
|
|
||||||
bytes getAssembledBytecode(bool _optimize = false) { return m_asm.optimise(_optimize).assemble(); }
|
bytes getAssembledBytecode(bool _optimize = false) { return m_asm.optimise(_optimize).assemble(); }
|
||||||
|
|
||||||
|
@ -157,14 +157,16 @@ bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize)
|
|||||||
return getBytecode();
|
return getBytecode();
|
||||||
}
|
}
|
||||||
|
|
||||||
eth::AssemblyItems const& CompilerStack::getAssemblyItems(string const& _contractName) const
|
eth::AssemblyItems const* CompilerStack::getAssemblyItems(string const& _contractName) const
|
||||||
{
|
{
|
||||||
return getContract(_contractName).compiler->getAssemblyItems();
|
Contract const& contract = getContract(_contractName);
|
||||||
|
return contract.compiler ? &getContract(_contractName).compiler->getAssemblyItems() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
eth::AssemblyItems const& CompilerStack::getRuntimeAssemblyItems(string const& _contractName) const
|
eth::AssemblyItems const* CompilerStack::getRuntimeAssemblyItems(string const& _contractName) const
|
||||||
{
|
{
|
||||||
return getContract(_contractName).compiler->getRuntimeAssemblyItems();
|
Contract const& contract = getContract(_contractName);
|
||||||
|
return contract.compiler ? &getContract(_contractName).compiler->getRuntimeAssemblyItems() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes const& CompilerStack::getBytecode(string const& _contractName) const
|
bytes const& CompilerStack::getBytecode(string const& _contractName) const
|
||||||
@ -182,9 +184,13 @@ dev::h256 CompilerStack::getContractCodeHash(string const& _contractName) const
|
|||||||
return dev::sha3(getRuntimeBytecode(_contractName));
|
return dev::sha3(getRuntimeBytecode(_contractName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerStack::streamAssembly(ostream& _outStream, string const& _contractName, StringMap _sourceCodes) const
|
void CompilerStack::streamAssembly(ostream& _outStream, string const& _contractName, StringMap _sourceCodes, bool _inJsonFormat) const
|
||||||
{
|
{
|
||||||
getContract(_contractName).compiler->streamAssembly(_outStream, _sourceCodes);
|
Contract const& contract = getContract(_contractName);
|
||||||
|
if (contract.compiler)
|
||||||
|
contract.compiler->streamAssembly(_outStream, _sourceCodes, _inJsonFormat);
|
||||||
|
else
|
||||||
|
_outStream << "Contract not fully implemented" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
string const& CompilerStack::getInterface(string const& _contractName) const
|
string const& CompilerStack::getInterface(string const& _contractName) const
|
||||||
|
@ -94,16 +94,17 @@ public:
|
|||||||
/// @returns the runtime bytecode for the contract, i.e. the code that is returned by the constructor.
|
/// @returns the runtime bytecode for the contract, i.e. the code that is returned by the constructor.
|
||||||
bytes const& getRuntimeBytecode(std::string const& _contractName = "") const;
|
bytes const& getRuntimeBytecode(std::string const& _contractName = "") const;
|
||||||
/// @returns normal contract assembly items
|
/// @returns normal contract assembly items
|
||||||
eth::AssemblyItems const& getAssemblyItems(std::string const& _contractName = "") const;
|
eth::AssemblyItems const* getAssemblyItems(std::string const& _contractName = "") const;
|
||||||
/// @returns runtime contract assembly items
|
/// @returns runtime contract assembly items
|
||||||
eth::AssemblyItems const& getRuntimeAssemblyItems(std::string const& _contractName = "") const;
|
eth::AssemblyItems const* getRuntimeAssemblyItems(std::string const& _contractName = "") const;
|
||||||
/// @returns hash of the runtime bytecode for the contract, i.e. the code that is returned by the constructor.
|
/// @returns hash of the runtime bytecode for the contract, i.e. the code that is returned by the constructor.
|
||||||
dev::h256 getContractCodeHash(std::string const& _contractName = "") const;
|
dev::h256 getContractCodeHash(std::string const& _contractName = "") const;
|
||||||
|
|
||||||
/// Streams a verbose version of the assembly to @a _outStream.
|
/// Streams a verbose version of the assembly to @a _outStream.
|
||||||
/// @arg _sourceCodes is the map of input files to source code strings
|
/// @arg _sourceCodes is the map of input files to source code strings
|
||||||
|
/// @arg _inJsonFromat shows whether the out should be in Json format
|
||||||
/// Prerequisite: Successful compilation.
|
/// Prerequisite: Successful compilation.
|
||||||
void streamAssembly(std::ostream& _outStream, std::string const& _contractName = "", StringMap _sourceCodes = StringMap()) const;
|
void streamAssembly(std::ostream& _outStream, std::string const& _contractName = "", StringMap _sourceCodes = StringMap(), bool _inJsonFormat = false) const;
|
||||||
|
|
||||||
/// Returns a string representing the contract interface in JSON.
|
/// Returns a string representing the contract interface in JSON.
|
||||||
/// Prerequisite: Successful call to parse or compile.
|
/// Prerequisite: Successful call to parse or compile.
|
||||||
|
Loading…
Reference in New Issue
Block a user