mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Compute canonical names of types for function signatures.
This commit is contained in:
parent
ce25ddfa6a
commit
bc609c55c0
@ -135,7 +135,7 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::inter
|
|||||||
FunctionType ftype(*v);
|
FunctionType ftype(*v);
|
||||||
solAssert(!!v->annotation().type.get(), "");
|
solAssert(!!v->annotation().type.get(), "");
|
||||||
functionsSeen.insert(v->name());
|
functionsSeen.insert(v->name());
|
||||||
FixedHash<4> hash(dev::sha3(ftype.externalSignature(v->name())));
|
FixedHash<4> hash(dev::sha3(ftype.externalSignature()));
|
||||||
m_interfaceFunctionList->push_back(make_pair(hash, make_shared<FunctionType>(*v)));
|
m_interfaceFunctionList->push_back(make_pair(hash, make_shared<FunctionType>(*v)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,6 +215,13 @@ TypePointer StructDefinition::type(ContractDefinition const*) const
|
|||||||
return make_shared<TypeType>(make_shared<StructType>(*this));
|
return make_shared<TypeType>(make_shared<StructType>(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeDeclarationAnnotation& StructDefinition::annotation() const
|
||||||
|
{
|
||||||
|
if (!m_annotation)
|
||||||
|
m_annotation = new TypeDeclarationAnnotation();
|
||||||
|
return static_cast<TypeDeclarationAnnotation&>(*m_annotation);
|
||||||
|
}
|
||||||
|
|
||||||
TypePointer EnumValue::type(ContractDefinition const*) const
|
TypePointer EnumValue::type(ContractDefinition const*) const
|
||||||
{
|
{
|
||||||
auto parentDef = dynamic_cast<EnumDefinition const*>(scope());
|
auto parentDef = dynamic_cast<EnumDefinition const*>(scope());
|
||||||
@ -227,6 +234,13 @@ TypePointer EnumDefinition::type(ContractDefinition const*) const
|
|||||||
return make_shared<TypeType>(make_shared<EnumType>(*this));
|
return make_shared<TypeType>(make_shared<EnumType>(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeDeclarationAnnotation& EnumDefinition::annotation() const
|
||||||
|
{
|
||||||
|
if (!m_annotation)
|
||||||
|
m_annotation = new TypeDeclarationAnnotation();
|
||||||
|
return static_cast<TypeDeclarationAnnotation&>(*m_annotation);
|
||||||
|
}
|
||||||
|
|
||||||
TypePointer FunctionDefinition::type(ContractDefinition const*) const
|
TypePointer FunctionDefinition::type(ContractDefinition const*) const
|
||||||
{
|
{
|
||||||
return make_shared<FunctionType>(*this);
|
return make_shared<FunctionType>(*this);
|
||||||
@ -234,7 +248,7 @@ TypePointer FunctionDefinition::type(ContractDefinition const*) const
|
|||||||
|
|
||||||
string FunctionDefinition::externalSignature() const
|
string FunctionDefinition::externalSignature() const
|
||||||
{
|
{
|
||||||
return FunctionType(*this).externalSignature(name());
|
return FunctionType(*this).externalSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
TypePointer ModifierDefinition::type(ContractDefinition const*) const
|
TypePointer ModifierDefinition::type(ContractDefinition const*) const
|
||||||
|
@ -352,6 +352,8 @@ public:
|
|||||||
|
|
||||||
virtual TypePointer type(ContractDefinition const* m_currentContract) const override;
|
virtual TypePointer type(ContractDefinition const* m_currentContract) const override;
|
||||||
|
|
||||||
|
virtual TypeDeclarationAnnotation& annotation() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ASTPointer<VariableDeclaration>> m_members;
|
std::vector<ASTPointer<VariableDeclaration>> m_members;
|
||||||
};
|
};
|
||||||
@ -372,6 +374,8 @@ public:
|
|||||||
|
|
||||||
virtual TypePointer type(ContractDefinition const* m_currentContract) const override;
|
virtual TypePointer type(ContractDefinition const* m_currentContract) const override;
|
||||||
|
|
||||||
|
virtual TypeDeclarationAnnotation& annotation() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ASTPointer<EnumValue>> m_members;
|
std::vector<ASTPointer<EnumValue>> m_members;
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,13 @@ struct ASTAnnotation
|
|||||||
virtual ~ASTAnnotation() {}
|
virtual ~ASTAnnotation() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ContractDefinitionAnnotation: ASTAnnotation
|
struct TypeDeclarationAnnotation: ASTAnnotation
|
||||||
|
{
|
||||||
|
/// The name of this type, prefixed by proper namespaces if globally accessible.
|
||||||
|
std::string canonicalName;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContractDefinitionAnnotation: TypeDeclarationAnnotation
|
||||||
{
|
{
|
||||||
/// Whether all functions are implemented.
|
/// Whether all functions are implemented.
|
||||||
bool isFullyImplemented = true;
|
bool isFullyImplemented = true;
|
||||||
|
@ -130,12 +130,15 @@ bool CompilerStack::parse()
|
|||||||
m_globalContext->setCurrentContract(*contract);
|
m_globalContext->setCurrentContract(*contract);
|
||||||
resolver.updateDeclaration(*m_globalContext->currentThis());
|
resolver.updateDeclaration(*m_globalContext->currentThis());
|
||||||
TypeChecker typeChecker;
|
TypeChecker typeChecker;
|
||||||
if (!typeChecker.checkTypeRequirements(*contract))
|
if (typeChecker.checkTypeRequirements(*contract))
|
||||||
typesFine = false;
|
{
|
||||||
m_errors += typeChecker.errors();
|
|
||||||
contract->setDevDocumentation(interfaceHandler.devDocumentation(*contract));
|
contract->setDevDocumentation(interfaceHandler.devDocumentation(*contract));
|
||||||
contract->setUserDocumentation(interfaceHandler.userDocumentation(*contract));
|
contract->setUserDocumentation(interfaceHandler.userDocumentation(*contract));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
typesFine = false;
|
||||||
m_contracts[contract->name()].contract = contract;
|
m_contracts[contract->name()].contract = contract;
|
||||||
|
m_errors += typeChecker.errors();
|
||||||
}
|
}
|
||||||
m_parseSuccessful = typesFine;
|
m_parseSuccessful = typesFine;
|
||||||
return m_parseSuccessful;
|
return m_parseSuccessful;
|
||||||
|
@ -40,8 +40,10 @@ namespace solidity
|
|||||||
class DeclarationContainer
|
class DeclarationContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit DeclarationContainer(Declaration const* _enclosingDeclaration = nullptr,
|
explicit DeclarationContainer(
|
||||||
DeclarationContainer const* _enclosingContainer = nullptr):
|
Declaration const* _enclosingDeclaration = nullptr,
|
||||||
|
DeclarationContainer const* _enclosingContainer = nullptr
|
||||||
|
):
|
||||||
m_enclosingDeclaration(_enclosingDeclaration), m_enclosingContainer(_enclosingContainer) {}
|
m_enclosingDeclaration(_enclosingDeclaration), m_enclosingContainer(_enclosingContainer) {}
|
||||||
/// Registers the declaration in the scope unless its name is already declared or the name is empty.
|
/// Registers the declaration in the scope unless its name is already declared or the name is empty.
|
||||||
/// @param _invisible if true, registers the declaration, reports name clashes but does not return it in @a resolveName
|
/// @param _invisible if true, registers the declaration, reports name clashes but does not return it in @a resolveName
|
||||||
|
@ -585,7 +585,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
}
|
}
|
||||||
if (!event.isAnonymous())
|
if (!event.isAnonymous())
|
||||||
{
|
{
|
||||||
m_context << u256(h256::Arith(dev::sha3(function.externalSignature(event.name()))));
|
m_context << u256(h256::Arith(dev::sha3(function.externalSignature())));
|
||||||
++numIndexed;
|
++numIndexed;
|
||||||
}
|
}
|
||||||
solAssert(numIndexed <= 4, "Too many indexed arguments.");
|
solAssert(numIndexed <= 4, "Too many indexed arguments.");
|
||||||
|
@ -64,11 +64,11 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef)
|
|||||||
method["constant"] = it.second->isConstant();
|
method["constant"] = it.second->isConstant();
|
||||||
method["inputs"] = populateParameters(
|
method["inputs"] = populateParameters(
|
||||||
externalFunctionType->parameterNames(),
|
externalFunctionType->parameterNames(),
|
||||||
externalFunctionType->parameterTypeNames()
|
externalFunctionType->parameterTypeNames(_contractDef.isLibrary())
|
||||||
);
|
);
|
||||||
method["outputs"] = populateParameters(
|
method["outputs"] = populateParameters(
|
||||||
externalFunctionType->returnParameterNames(),
|
externalFunctionType->returnParameterNames(),
|
||||||
externalFunctionType->returnParameterTypeNames()
|
externalFunctionType->returnParameterTypeNames(_contractDef.isLibrary())
|
||||||
);
|
);
|
||||||
abi.append(method);
|
abi.append(method);
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef)
|
|||||||
solAssert(!!externalFunction, "");
|
solAssert(!!externalFunction, "");
|
||||||
method["inputs"] = populateParameters(
|
method["inputs"] = populateParameters(
|
||||||
externalFunction->parameterNames(),
|
externalFunction->parameterNames(),
|
||||||
externalFunction->parameterTypeNames()
|
externalFunction->parameterTypeNames(_contractDef.isLibrary())
|
||||||
);
|
);
|
||||||
abi.append(method);
|
abi.append(method);
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef)
|
|||||||
{
|
{
|
||||||
Json::Value input;
|
Json::Value input;
|
||||||
input["name"] = p->name();
|
input["name"] = p->name();
|
||||||
input["type"] = p->annotation().type->toString(true);
|
input["type"] = p->annotation().type->canonicalName(false);
|
||||||
input["indexed"] = p->isIndexed();
|
input["indexed"] = p->isIndexed();
|
||||||
params.append(input);
|
params.append(input);
|
||||||
}
|
}
|
||||||
@ -125,16 +125,24 @@ string InterfaceHandler::ABISolidityInterface(ContractDefinition const& _contrac
|
|||||||
ret +=
|
ret +=
|
||||||
"function " +
|
"function " +
|
||||||
_contractDef.name() +
|
_contractDef.name() +
|
||||||
populateParameters(externalFunction->parameterNames(), externalFunction->parameterTypeNames()) +
|
populateParameters(
|
||||||
|
externalFunction->parameterNames(),
|
||||||
|
externalFunction->parameterTypeNames(_contractDef.isLibrary())
|
||||||
|
) +
|
||||||
";";
|
";";
|
||||||
}
|
}
|
||||||
for (auto const& it: _contractDef.interfaceFunctions())
|
for (auto const& it: _contractDef.interfaceFunctions())
|
||||||
{
|
{
|
||||||
ret += "function " + it.second->declaration().name() +
|
ret += "function " + it.second->declaration().name() +
|
||||||
populateParameters(it.second->parameterNames(), it.second->parameterTypeNames()) +
|
populateParameters(
|
||||||
(it.second->isConstant() ? "constant " : "");
|
it.second->parameterNames(),
|
||||||
|
it.second->parameterTypeNames(_contractDef.isLibrary())
|
||||||
|
) + (it.second->isConstant() ? "constant " : "");
|
||||||
if (it.second->returnParameterTypes().size())
|
if (it.second->returnParameterTypes().size())
|
||||||
ret += "returns" + populateParameters(it.second->returnParameterNames(), it.second->returnParameterTypeNames());
|
ret += "returns" + populateParameters(
|
||||||
|
it.second->returnParameterNames(),
|
||||||
|
it.second->returnParameterTypeNames(_contractDef.isLibrary())
|
||||||
|
);
|
||||||
else if (ret.back() == ' ')
|
else if (ret.back() == ' ')
|
||||||
ret.pop_back();
|
ret.pop_back();
|
||||||
ret += ";";
|
ret += ";";
|
||||||
|
@ -263,6 +263,7 @@ DeclarationRegistrationHelper::DeclarationRegistrationHelper(map<ASTNode const*,
|
|||||||
bool DeclarationRegistrationHelper::visit(ContractDefinition& _contract)
|
bool DeclarationRegistrationHelper::visit(ContractDefinition& _contract)
|
||||||
{
|
{
|
||||||
registerDeclaration(_contract, true);
|
registerDeclaration(_contract, true);
|
||||||
|
_contract.annotation().canonicalName = currentCanonicalName();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,6 +275,7 @@ void DeclarationRegistrationHelper::endVisit(ContractDefinition&)
|
|||||||
bool DeclarationRegistrationHelper::visit(StructDefinition& _struct)
|
bool DeclarationRegistrationHelper::visit(StructDefinition& _struct)
|
||||||
{
|
{
|
||||||
registerDeclaration(_struct, true);
|
registerDeclaration(_struct, true);
|
||||||
|
_struct.annotation().canonicalName = currentCanonicalName();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,6 +287,7 @@ void DeclarationRegistrationHelper::endVisit(StructDefinition&)
|
|||||||
bool DeclarationRegistrationHelper::visit(EnumDefinition& _enum)
|
bool DeclarationRegistrationHelper::visit(EnumDefinition& _enum)
|
||||||
{
|
{
|
||||||
registerDeclaration(_enum, true);
|
registerDeclaration(_enum, true);
|
||||||
|
_enum.annotation().canonicalName = currentCanonicalName();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,5 +403,21 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
|
|||||||
enterNewSubScope(_declaration);
|
enterNewSubScope(_declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string DeclarationRegistrationHelper::currentCanonicalName() const
|
||||||
|
{
|
||||||
|
string ret;
|
||||||
|
for (
|
||||||
|
Declaration const* scope = m_currentScope;
|
||||||
|
scope != nullptr;
|
||||||
|
scope = m_scopes[scope].enclosingDeclaration()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!ret.empty())
|
||||||
|
ret = "." + ret;
|
||||||
|
ret = scope->name() + ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,9 @@ private:
|
|||||||
void closeCurrentScope();
|
void closeCurrentScope();
|
||||||
void registerDeclaration(Declaration& _declaration, bool _opensScope);
|
void registerDeclaration(Declaration& _declaration, bool _opensScope);
|
||||||
|
|
||||||
|
/// @returns the canonical name of the current scope.
|
||||||
|
std::string currentCanonicalName() const;
|
||||||
|
|
||||||
std::map<ASTNode const*, DeclarationContainer>& m_scopes;
|
std::map<ASTNode const*, DeclarationContainer>& m_scopes;
|
||||||
Declaration const* m_currentScope;
|
Declaration const* m_currentScope;
|
||||||
VariableScope* m_currentFunction;
|
VariableScope* m_currentFunction;
|
||||||
|
@ -299,7 +299,7 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co
|
|||||||
if (f->isPartOfExternalInterface())
|
if (f->isPartOfExternalInterface())
|
||||||
{
|
{
|
||||||
auto functionType = make_shared<FunctionType>(*f);
|
auto functionType = make_shared<FunctionType>(*f);
|
||||||
externalDeclarations[functionType->externalSignature(f->name())].push_back(
|
externalDeclarations[functionType->externalSignature()].push_back(
|
||||||
make_pair(f.get(), functionType)
|
make_pair(f.get(), functionType)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -307,7 +307,7 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co
|
|||||||
if (v->isPartOfExternalInterface())
|
if (v->isPartOfExternalInterface())
|
||||||
{
|
{
|
||||||
auto functionType = make_shared<FunctionType>(*v);
|
auto functionType = make_shared<FunctionType>(*v);
|
||||||
externalDeclarations[functionType->externalSignature(v->name())].push_back(
|
externalDeclarations[functionType->externalSignature()].push_back(
|
||||||
make_pair(v.get(), functionType)
|
make_pair(v.get(), functionType)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -403,7 +403,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
|||||||
if (!type(*var)->canLiveOutsideStorage())
|
if (!type(*var)->canLiveOutsideStorage())
|
||||||
typeError(*var, "Type is required to live outside storage.");
|
typeError(*var, "Type is required to live outside storage.");
|
||||||
if (_function.visibility() >= FunctionDefinition::Visibility::Public && !(type(*var)->interfaceType(isLibraryFunction)))
|
if (_function.visibility() >= FunctionDefinition::Visibility::Public && !(type(*var)->interfaceType(isLibraryFunction)))
|
||||||
typeError(*var, "Internal type is not allowed for public and external functions.");
|
fatalTypeError(*var, "Internal type is not allowed for public or external functions.");
|
||||||
}
|
}
|
||||||
for (ASTPointer<ModifierInvocation> const& modifier: _function.modifiers())
|
for (ASTPointer<ModifierInvocation> const& modifier: _function.modifiers())
|
||||||
visitManually(
|
visitManually(
|
||||||
|
@ -839,6 +839,25 @@ string ArrayType::toString(bool _short) const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string ArrayType::canonicalName(bool _addDataLocation) const
|
||||||
|
{
|
||||||
|
string ret;
|
||||||
|
if (isString())
|
||||||
|
ret = "string";
|
||||||
|
else if (isByteArray())
|
||||||
|
ret = "bytes";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = baseType()->canonicalName(false) + "[";
|
||||||
|
if (!isDynamicallySized())
|
||||||
|
ret += length().str();
|
||||||
|
ret += "]";
|
||||||
|
}
|
||||||
|
if (_addDataLocation && location() == DataLocation::Storage)
|
||||||
|
ret += " storage";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
TypePointer ArrayType::encodingType() const
|
TypePointer ArrayType::encodingType() const
|
||||||
{
|
{
|
||||||
if (location() == DataLocation::Storage)
|
if (location() == DataLocation::Storage)
|
||||||
@ -912,6 +931,11 @@ string ContractType::toString(bool) const
|
|||||||
m_contract.name();
|
m_contract.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string ContractType::canonicalName(bool) const
|
||||||
|
{
|
||||||
|
return m_contract.annotation().canonicalName;
|
||||||
|
}
|
||||||
|
|
||||||
MemberList const& ContractType::members() const
|
MemberList const& ContractType::members() const
|
||||||
{
|
{
|
||||||
// We need to lazy-initialize it because of recursive references.
|
// We need to lazy-initialize it because of recursive references.
|
||||||
@ -1093,6 +1117,14 @@ TypePointer StructType::copyForLocation(DataLocation _location, bool _isPointer)
|
|||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string StructType::canonicalName(bool _addDataLocation) const
|
||||||
|
{
|
||||||
|
string ret = m_struct.annotation().canonicalName;
|
||||||
|
if (_addDataLocation && location() == DataLocation::Storage)
|
||||||
|
ret += " storage";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
FunctionTypePointer StructType::constructorType() const
|
FunctionTypePointer StructType::constructorType() const
|
||||||
{
|
{
|
||||||
TypePointers paramTypes;
|
TypePointers paramTypes;
|
||||||
@ -1168,6 +1200,11 @@ string EnumType::toString(bool) const
|
|||||||
return string("enum ") + m_enum.name();
|
return string("enum ") + m_enum.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string EnumType::canonicalName(bool) const
|
||||||
|
{
|
||||||
|
return m_enum.annotation().canonicalName;
|
||||||
|
}
|
||||||
|
|
||||||
bool EnumType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
bool EnumType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||||
{
|
{
|
||||||
return _convertTo.category() == category() || _convertTo.category() == Category::Integer;
|
return _convertTo.category() == category() || _convertTo.category() == Category::Integer;
|
||||||
@ -1483,15 +1520,13 @@ bool FunctionType::isBareCall() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string FunctionType::externalSignature(std::string const& _name) const
|
string FunctionType::externalSignature() const
|
||||||
{
|
{
|
||||||
std::string funcName = _name;
|
solAssert(m_declaration != nullptr, "External signature of function needs declaration");
|
||||||
if (_name == "")
|
|
||||||
{
|
bool _inLibrary = dynamic_cast<ContractDefinition const&>(*m_declaration->scope()).isLibrary();
|
||||||
solAssert(m_declaration != nullptr, "Function type without name needs a declaration");
|
|
||||||
funcName = m_declaration->name();
|
string ret = m_declaration->name() + "(";
|
||||||
}
|
|
||||||
string ret = funcName + "(";
|
|
||||||
|
|
||||||
FunctionTypePointer external = interfaceFunctionType();
|
FunctionTypePointer external = interfaceFunctionType();
|
||||||
solAssert(!!external, "External function type requested.");
|
solAssert(!!external, "External function type requested.");
|
||||||
@ -1499,7 +1534,7 @@ string FunctionType::externalSignature(std::string const& _name) const
|
|||||||
for (auto it = externalParameterTypes.cbegin(); it != externalParameterTypes.cend(); ++it)
|
for (auto it = externalParameterTypes.cbegin(); it != externalParameterTypes.cend(); ++it)
|
||||||
{
|
{
|
||||||
solAssert(!!(*it), "Parameter should have external type");
|
solAssert(!!(*it), "Parameter should have external type");
|
||||||
ret += (*it)->toString(true) + (it + 1 == externalParameterTypes.cend() ? "" : ",");
|
ret += (*it)->canonicalName(_inLibrary) + (it + 1 == externalParameterTypes.cend() ? "" : ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret + ")";
|
return ret + ")";
|
||||||
@ -1567,20 +1602,20 @@ FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary) const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> const FunctionType::parameterTypeNames() const
|
vector<string> const FunctionType::parameterTypeNames(bool _addDataLocation) const
|
||||||
{
|
{
|
||||||
vector<string> names;
|
vector<string> names;
|
||||||
for (TypePointer const& t: m_parameterTypes)
|
for (TypePointer const& t: m_parameterTypes)
|
||||||
names.push_back(t->toString(true));
|
names.push_back(t->canonicalName(_addDataLocation));
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> const FunctionType::returnParameterTypeNames() const
|
vector<string> const FunctionType::returnParameterTypeNames(bool _addDataLocation) const
|
||||||
{
|
{
|
||||||
vector<string> names;
|
vector<string> names;
|
||||||
for (TypePointer const& t: m_returnParameterTypes)
|
for (TypePointer const& t: m_returnParameterTypes)
|
||||||
names.push_back(t->toString(true));
|
names.push_back(t->canonicalName(_addDataLocation));
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
@ -1607,6 +1642,11 @@ string MappingType::toString(bool _short) const
|
|||||||
return "mapping(" + keyType()->toString(_short) + " => " + valueType()->toString(_short) + ")";
|
return "mapping(" + keyType()->toString(_short) + " => " + valueType()->toString(_short) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string MappingType::canonicalName(bool) const
|
||||||
|
{
|
||||||
|
return "mapping(" + keyType()->canonicalName(false) + " => " + valueType()->canonicalName(false) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
u256 VoidType::storageSize() const
|
u256 VoidType::storageSize() const
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
|
@ -218,6 +218,9 @@ public:
|
|||||||
|
|
||||||
virtual std::string toString(bool _short) const = 0;
|
virtual std::string toString(bool _short) const = 0;
|
||||||
std::string toString() const { return toString(false); }
|
std::string toString() const { return toString(false); }
|
||||||
|
/// @returns the canonical name of this type for use in function signatures.
|
||||||
|
/// @param _addDataLocation if true, includes data location for reference types if it is "storage".
|
||||||
|
virtual std::string canonicalName(bool /*_addDataLocation*/) const { return toString(true); }
|
||||||
virtual u256 literalValue(Literal const*) const
|
virtual u256 literalValue(Literal const*) const
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
@ -501,6 +504,7 @@ public:
|
|||||||
virtual bool canLiveOutsideStorage() const override { return m_baseType->canLiveOutsideStorage(); }
|
virtual bool canLiveOutsideStorage() const override { return m_baseType->canLiveOutsideStorage(); }
|
||||||
virtual unsigned sizeOnStack() const override;
|
virtual unsigned sizeOnStack() const override;
|
||||||
virtual std::string toString(bool _short) const override;
|
virtual std::string toString(bool _short) const override;
|
||||||
|
virtual std::string canonicalName(bool _addDataLocation) const override;
|
||||||
virtual MemberList const& members() const override
|
virtual MemberList const& members() const override
|
||||||
{
|
{
|
||||||
return isString() ? EmptyMemberList : s_arrayTypeMemberList;
|
return isString() ? EmptyMemberList : s_arrayTypeMemberList;
|
||||||
@ -554,6 +558,7 @@ public:
|
|||||||
virtual bool canLiveOutsideStorage() const override { return true; }
|
virtual bool canLiveOutsideStorage() const override { return true; }
|
||||||
virtual bool isValueType() const override { return true; }
|
virtual bool isValueType() const override { return true; }
|
||||||
virtual std::string toString(bool _short) const override;
|
virtual std::string toString(bool _short) const override;
|
||||||
|
virtual std::string canonicalName(bool _addDataLocation) const override;
|
||||||
|
|
||||||
virtual MemberList const& members() const override;
|
virtual MemberList const& members() const override;
|
||||||
virtual TypePointer encodingType() const override
|
virtual TypePointer encodingType() const override
|
||||||
@ -617,6 +622,8 @@ public:
|
|||||||
|
|
||||||
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
|
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
|
||||||
|
|
||||||
|
virtual std::string canonicalName(bool _addDataLocation) const override;
|
||||||
|
|
||||||
/// @returns a function that peforms the type conversion between a list of struct members
|
/// @returns a function that peforms the type conversion between a list of struct members
|
||||||
/// and a memory struct of this type.
|
/// and a memory struct of this type.
|
||||||
FunctionTypePointer constructorType() const;
|
FunctionTypePointer constructorType() const;
|
||||||
@ -652,6 +659,7 @@ public:
|
|||||||
virtual unsigned storageBytes() const override;
|
virtual unsigned storageBytes() const override;
|
||||||
virtual bool canLiveOutsideStorage() const override { return true; }
|
virtual bool canLiveOutsideStorage() const override { return true; }
|
||||||
virtual std::string toString(bool _short) const override;
|
virtual std::string toString(bool _short) const override;
|
||||||
|
virtual std::string canonicalName(bool _addDataLocation) const override;
|
||||||
virtual bool isValueType() const override { return true; }
|
virtual bool isValueType() const override { return true; }
|
||||||
|
|
||||||
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||||
@ -756,10 +764,10 @@ public:
|
|||||||
|
|
||||||
TypePointers const& parameterTypes() const { return m_parameterTypes; }
|
TypePointers const& parameterTypes() const { return m_parameterTypes; }
|
||||||
std::vector<std::string> const& parameterNames() const { return m_parameterNames; }
|
std::vector<std::string> const& parameterNames() const { return m_parameterNames; }
|
||||||
std::vector<std::string> const parameterTypeNames() const;
|
std::vector<std::string> const parameterTypeNames(bool _addDataLocation) const;
|
||||||
TypePointers const& returnParameterTypes() const { return m_returnParameterTypes; }
|
TypePointers const& returnParameterTypes() const { return m_returnParameterTypes; }
|
||||||
std::vector<std::string> const& returnParameterNames() const { return m_returnParameterNames; }
|
std::vector<std::string> const& returnParameterNames() const { return m_returnParameterNames; }
|
||||||
std::vector<std::string> const returnParameterTypeNames() const;
|
std::vector<std::string> const returnParameterTypeNames(bool _addDataLocation) const;
|
||||||
|
|
||||||
virtual bool operator==(Type const& _other) const override;
|
virtual bool operator==(Type const& _other) const override;
|
||||||
virtual std::string toString(bool _short) const override;
|
virtual std::string toString(bool _short) const override;
|
||||||
@ -786,9 +794,7 @@ public:
|
|||||||
bool isBareCall() const;
|
bool isBareCall() const;
|
||||||
Location const& location() const { return m_location; }
|
Location const& location() const { return m_location; }
|
||||||
/// @returns the external signature of this function type given the function name
|
/// @returns the external signature of this function type given the function name
|
||||||
/// If @a _name is not provided (empty string) then the @c m_declaration member of the
|
std::string externalSignature() const;
|
||||||
/// function type is used
|
|
||||||
std::string externalSignature(std::string const& _name = "") const;
|
|
||||||
/// @returns the external identifier of this function (the hash of the signature).
|
/// @returns the external identifier of this function (the hash of the signature).
|
||||||
u256 externalIdentifier() const;
|
u256 externalIdentifier() const;
|
||||||
Declaration const& declaration() const
|
Declaration const& declaration() const
|
||||||
@ -849,6 +855,7 @@ public:
|
|||||||
|
|
||||||
virtual bool operator==(Type const& _other) const override;
|
virtual bool operator==(Type const& _other) const override;
|
||||||
virtual std::string toString(bool _short) const override;
|
virtual std::string toString(bool _short) const override;
|
||||||
|
virtual std::string canonicalName(bool _addDataLocation) const override;
|
||||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||||
virtual TypePointer encodingType() const override
|
virtual TypePointer encodingType() const override
|
||||||
{
|
{
|
||||||
|
@ -595,6 +595,36 @@ BOOST_AUTO_TEST_CASE(strings_and_arrays)
|
|||||||
checkInterface(sourceCode, interface);
|
checkInterface(sourceCode, interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(library_function)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
library test {
|
||||||
|
struct StructType { uint a; }
|
||||||
|
function f(StructType storage b, uint[] storage c, test d) returns (uint[] e, StructType storage f){}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
char const* interface = R"(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"constant" : false,
|
||||||
|
"name": "f",
|
||||||
|
"inputs": [
|
||||||
|
{ "name": "b", "type": "test.StructType storage" },
|
||||||
|
{ "name": "c", "type": "uint256[] storage" },
|
||||||
|
{ "name": "d", "type": "test" }
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{ "name": "e", "type": "uint256[]" },
|
||||||
|
{ "name": "f", "type": "test.StructType storage" }
|
||||||
|
],
|
||||||
|
"type" : "function"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)";
|
||||||
|
checkInterface(sourceCode, interface);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5383,32 +5383,6 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library)
|
|||||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17)));
|
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(differentiate_storage_and_memory_in_libraries)
|
|
||||||
{
|
|
||||||
char const* sourceCode = R"(
|
|
||||||
library Lib {
|
|
||||||
function f(uint[] storage x) returns (uint) { return 1; }
|
|
||||||
function f(uint[] memory x) returns (uint) { return 2; }
|
|
||||||
}
|
|
||||||
contract Test {
|
|
||||||
uint[] data;
|
|
||||||
function f() returns (uint a,)
|
|
||||||
{
|
|
||||||
uint[] memory d = data;
|
|
||||||
Lib.f(d)
|
|
||||||
data["abc"].length = 20;
|
|
||||||
data["abc"][4] = 9;
|
|
||||||
data["abc"][17] = 3;
|
|
||||||
a = Lib.find(data["abc"], 9);
|
|
||||||
b = Lib.find(data["abc"], 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
compileAndRun(sourceCode, 0, "Lib");
|
|
||||||
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
|
|
||||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17)));
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(short_strings)
|
BOOST_AUTO_TEST_CASE(short_strings)
|
||||||
{
|
{
|
||||||
// This test verifies that the byte array encoding that combines length and data works
|
// This test verifies that the byte array encoding that combines length and data works
|
||||||
|
@ -142,6 +142,21 @@ BOOST_AUTO_TEST_CASE(inheritance)
|
|||||||
sourcePart(*contract.definedFunctions().at(1))}));
|
sourcePart(*contract.definedFunctions().at(1))}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(libraries)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
library Lib {
|
||||||
|
struct Str { uint a; }
|
||||||
|
enum E { E1, E2 }
|
||||||
|
function f(uint[] x,Str storage y,E z) external;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
ContractDefinition const& contract = checkInterface(sourceCode);
|
||||||
|
set<string> expectedFunctions({"function f(uint256[] x,Lib.Str y,Lib.E z);"});
|
||||||
|
BOOST_REQUIRE_EQUAL(1, contract.definedFunctions().size());
|
||||||
|
BOOST_CHECK(expectedFunctions == set<string>({sourcePart(*contract.definedFunctions().at(0))}));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -933,24 +933,24 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
|
|||||||
BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr);
|
BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr);
|
||||||
FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()");
|
FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()");
|
||||||
BOOST_REQUIRE(function && function->hasDeclaration());
|
BOOST_REQUIRE(function && function->hasDeclaration());
|
||||||
auto returnParams = function->returnParameterTypeNames();
|
auto returnParams = function->returnParameterTypeNames(false);
|
||||||
BOOST_CHECK_EQUAL(returnParams.at(0), "uint256");
|
BOOST_CHECK_EQUAL(returnParams.at(0), "uint256");
|
||||||
BOOST_CHECK(function->isConstant());
|
BOOST_CHECK(function->isConstant());
|
||||||
|
|
||||||
function = retrieveFunctionBySignature(contract, "map(uint256)");
|
function = retrieveFunctionBySignature(contract, "map(uint256)");
|
||||||
BOOST_REQUIRE(function && function->hasDeclaration());
|
BOOST_REQUIRE(function && function->hasDeclaration());
|
||||||
auto params = function->parameterTypeNames();
|
auto params = function->parameterTypeNames(false);
|
||||||
BOOST_CHECK_EQUAL(params.at(0), "uint256");
|
BOOST_CHECK_EQUAL(params.at(0), "uint256");
|
||||||
returnParams = function->returnParameterTypeNames();
|
returnParams = function->returnParameterTypeNames(false);
|
||||||
BOOST_CHECK_EQUAL(returnParams.at(0), "bytes4");
|
BOOST_CHECK_EQUAL(returnParams.at(0), "bytes4");
|
||||||
BOOST_CHECK(function->isConstant());
|
BOOST_CHECK(function->isConstant());
|
||||||
|
|
||||||
function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)");
|
function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)");
|
||||||
BOOST_REQUIRE(function && function->hasDeclaration());
|
BOOST_REQUIRE(function && function->hasDeclaration());
|
||||||
params = function->parameterTypeNames();
|
params = function->parameterTypeNames(false);
|
||||||
BOOST_CHECK_EQUAL(params.at(0), "uint256");
|
BOOST_CHECK_EQUAL(params.at(0), "uint256");
|
||||||
BOOST_CHECK_EQUAL(params.at(1), "uint256");
|
BOOST_CHECK_EQUAL(params.at(1), "uint256");
|
||||||
returnParams = function->returnParameterTypeNames();
|
returnParams = function->returnParameterTypeNames(false);
|
||||||
BOOST_CHECK_EQUAL(returnParams.at(0), "bytes4");
|
BOOST_CHECK_EQUAL(returnParams.at(0), "bytes4");
|
||||||
BOOST_CHECK(function->isConstant());
|
BOOST_CHECK(function->isConstant());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user