Skip to content

Commit

Permalink
Merge pull request #12 from tonlabs/0.23
Browse files Browse the repository at this point in the history
latest fixes
  • Loading branch information
BorisI authored May 6, 2020
2 parents ecb0182 + 7ce4bd6 commit 382bada
Show file tree
Hide file tree
Showing 31 changed files with 1,107 additions and 848 deletions.
Binary file modified README.md
Binary file not shown.
30 changes: 18 additions & 12 deletions compiler/libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,11 +1269,6 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
var.accept(*this);

BoolResult result = valueComponentType->isImplicitlyConvertibleTo(*var.annotation().type);

if (auto map1 = dynamic_cast<const MappingType*>(valueComponentType))
if (auto map2 = dynamic_cast<const MappingType*>(var.annotation().type))
result = map1->isImplicitlyConvertibleTo(map2);

if (!result)
{
auto errorMsg = "Type " +
Expand Down Expand Up @@ -2031,7 +2026,14 @@ TypeChecker::isArgumentAPublicFunction(FunctionCall const& _functionCall) {
m_errorReporter.fatalTypeError(expr->location(), errorText);
}
auto identifier = dynamic_cast<Identifier const*>(expr);
Declaration const* declaration = identifier->annotation().referencedDeclaration;
Declaration const* declaration = nullptr;
if (identifier)
declaration = identifier->annotation().referencedDeclaration;
else if (auto member = dynamic_cast<MemberAccess const *>(expr)) {
declaration = member->annotation().referencedDeclaration;
}
if (!declaration)
m_errorReporter.fatalTypeError(expr->location(), errorText);
if (!declaration->isPublic()) {
m_errorReporter.fatalTypeError(expr->location(), errorText);
}
Expand Down Expand Up @@ -3066,6 +3068,16 @@ void TypeChecker::endVisit(ElementaryTypeNameExpression const& _expr)
_expr.annotation().isPure = true;
}

void TypeChecker::endVisit(MappingNameExpression const& _expr)
{
_expr.annotation().type = TypeProvider::typeType(TypeProvider::mapping(
_expr.type().keyType().annotation().type,
_expr.type().valueType().annotation().type,
DataLocation::Memory
));
_expr.annotation().isPure = true;
}

void TypeChecker::endVisit(Literal const& _literal)
{
if (_literal.looksLikeAddress())
Expand Down Expand Up @@ -3174,14 +3186,8 @@ bool TypeChecker::expectType(Expression const& _expression, Type const& _expecte
{
_expression.accept(*this);


BoolResult result = type(_expression)->isImplicitlyConvertibleTo(_expectedType);

if (auto map1 = dynamic_cast<const MappingType*>(type(_expression)))
if (auto map2 = dynamic_cast<const MappingType*>(&_expectedType))
result = map1->isImplicitlyConvertibleTo(map2);


if (!result)
{
auto errorMsg = "Type " +
Expand Down
1 change: 1 addition & 0 deletions compiler/libsolidity/analysis/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class TypeChecker: private ASTConstVisitor
bool visit(IndexRangeAccess const& _indexRangeAccess) override;
bool visit(Identifier const& _identifier) override;
void endVisit(ElementaryTypeNameExpression const& _expr) override;
void endVisit(MappingNameExpression const& _expr) override;
void endVisit(Literal const& _literal) override;
bool visit(Mapping const& _mapping) override;

Expand Down
25 changes: 25 additions & 0 deletions compiler/libsolidity/ast/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -2015,6 +2015,31 @@ class ElementaryTypeNameExpression: public PrimaryExpression
ASTPointer<ElementaryTypeName> m_type;
};

/**
* mapping(uint=>address)
* for example slice.decode(mapping(uint=>address))
*/
class MappingNameExpression : public PrimaryExpression
{
public:
MappingNameExpression(
int64_t _id,
SourceLocation const& _location,
ASTPointer<Mapping> const& _type
):
PrimaryExpression(_id, _location),
m_type(_type)
{
}
void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override;

Mapping const& type() const { return *m_type; }

private:
ASTPointer<Mapping> m_type;
};

/**
* A literal string or number. @see ExpressionCompiler::endVisit() is used to actually parse its value.
*/
Expand Down
4 changes: 4 additions & 0 deletions compiler/libsolidity/ast/ASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class ASTVisitor
virtual bool visit(ElementaryTypeNameExpression& _node) { return visitNode(_node); }
virtual bool visit(Literal& _node) { return visitNode(_node); }
virtual bool visit(StructuredDocumentation& _node) { return visitNode(_node); }
virtual bool visit(MappingNameExpression& _node) { return visitNode(_node); }

virtual void endVisit(SourceUnit& _node) { endVisitNode(_node); }
virtual void endVisit(PragmaDirective& _node) { endVisitNode(_node); }
Expand Down Expand Up @@ -145,6 +146,7 @@ class ASTVisitor
virtual void endVisit(ElementaryTypeNameExpression& _node) { endVisitNode(_node); }
virtual void endVisit(Literal& _node) { endVisitNode(_node); }
virtual void endVisit(StructuredDocumentation& _node) { endVisitNode(_node); }
virtual void endVisit(MappingNameExpression& _node) { endVisitNode(_node); }

protected:
/// Generic function called by default for each node, to be overridden by derived classes
Expand Down Expand Up @@ -210,6 +212,7 @@ class ASTConstVisitor
virtual bool visit(ElementaryTypeNameExpression const& _node) { return visitNode(_node); }
virtual bool visit(Literal const& _node) { return visitNode(_node); }
virtual bool visit(StructuredDocumentation const& _node) { return visitNode(_node); }
virtual bool visit(MappingNameExpression const& _node) { return visitNode(_node); }

virtual void endVisit(SourceUnit const& _node) { endVisitNode(_node); }
virtual void endVisit(PragmaDirective const& _node) { endVisitNode(_node); }
Expand Down Expand Up @@ -262,6 +265,7 @@ class ASTConstVisitor
virtual void endVisit(ElementaryTypeNameExpression const& _node) { endVisitNode(_node); }
virtual void endVisit(Literal const& _node) { endVisitNode(_node); }
virtual void endVisit(StructuredDocumentation const& _node) { endVisitNode(_node); }
virtual void endVisit(MappingNameExpression const& _node) { endVisitNode(_node); }

protected:
/// Generic function called by default for each node, to be overridden by derived classes
Expand Down
18 changes: 18 additions & 0 deletions compiler/libsolidity/ast/AST_accept.h
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,24 @@ void ElementaryTypeNameExpression::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this);
}

void MappingNameExpression::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
{
m_type->accept(_visitor);
}
_visitor.endVisit(*this);
}

void MappingNameExpression::accept(ASTConstVisitor& _visitor) const
{
if (_visitor.visit(*this))
{
m_type->accept(_visitor);
}
_visitor.endVisit(*this);
}

void Literal::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
Expand Down
86 changes: 25 additions & 61 deletions compiler/libsolidity/ast/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1591,39 +1591,15 @@ BoolResult ArrayType::isImplicitlyConvertibleTo(Type const& _convertTo) const
if (_convertTo.category() != category())
return false;
auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
if (convertTo.isByteArray() != isByteArray() || convertTo.isString() != isString())
return false;
// memory/calldata to storage can be converted, but only to a direct storage reference
if (convertTo.location() == DataLocation::Storage && location() != DataLocation::Storage && convertTo.isPointer())
return false;
if (convertTo.location() == DataLocation::CallData && location() != convertTo.location())
return false;
if (convertTo.location() == DataLocation::Storage && !convertTo.isPointer())
{
// Less restrictive conversion, since we need to copy anyway.
if (!baseType()->isImplicitlyConvertibleTo(*convertTo.baseType()))
return false;
if (convertTo.isDynamicallySized())
return true;
return !isDynamicallySized() && convertTo.length() >= length();
}
else
{
// Conversion to storage pointer or to memory, we de not copy element-for-element here, so
// require that the base type is the same, not only convertible.
// This disallows assignment of nested dynamic arrays from storage to memory for now.
if (
*TypeProvider::withLocationIfReference(location(), baseType()) !=
*TypeProvider::withLocationIfReference(location(), convertTo.baseType())
)
return false;
if (isDynamicallySized() != convertTo.isDynamicallySized())
return false;
// We also require that the size is the same.
if (!isDynamicallySized() && length() != convertTo.length())
return false;
return true;
if (isByteArray() || isString())
return convertTo.isByteArray() || convertTo.isString();
Type const* t0 = baseType();
Type const* t1 = convertTo.baseType();
while (dynamic_cast<ArrayType const*>(t0) && dynamic_cast<ArrayType const*>(t1)) {
t0 = dynamic_cast<ArrayType const*>(t0)->baseType();
t1 = dynamic_cast<ArrayType const*>(t1)->baseType();
}
return *t0 == *t1;
}

BoolResult ArrayType::isExplicitlyConvertibleTo(Type const& _convertTo) const
Expand Down Expand Up @@ -3544,10 +3520,13 @@ Type const* MappingType::encodingType() const
return TypeProvider::integer(256, IntegerType::Modifier::Unsigned);
}

BoolResult MappingType::isImplicitlyConvertibleTo(const MappingType * _other) const
BoolResult MappingType::isImplicitlyConvertibleTo(Type const& _other) const
{
return keyType()->isImplicitlyConvertibleTo(*_other->keyType()) &&
valueType()->isImplicitlyConvertibleTo(*_other->valueType());
if (_other.category() != category())
return false;
auto map = dynamic_cast<MappingType const*>(&_other);
return keyType()->isImplicitlyConvertibleTo(*map->keyType()) &&
valueType()->isImplicitlyConvertibleTo(*map->valueType());
}

string MappingType::richIdentifier() const
Expand Down Expand Up @@ -3825,24 +3804,6 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const
{"resetStorage", TypeProvider::function(strings(), strings(), FunctionType::Kind::TVMResetStorage, false, StateMutability::NonPayable)},
{"log", TypeProvider::function(strings{"bytes32"}, strings{}, FunctionType::Kind::LogTVM,false, StateMutability::Pure)}
};
members.emplace_back("transfer", TypeProvider::function(
TypePointers{TypeProvider::address(), TypeProvider::integer(128, IntegerType::Modifier::Unsigned),
TypeProvider::boolean(), TypeProvider::integer(16, IntegerType::Modifier::Unsigned)},
TypePointers{},
strings{string(), string(), string(), string()},
strings{},
FunctionType::Kind::TVMTransfer,
false, StateMutability::Pure
));
members.emplace_back("transfer", TypeProvider::function(
TypePointers{TypeProvider::address(), TypeProvider::integer(128, IntegerType::Modifier::Unsigned),
TypeProvider::boolean(), TypeProvider::integer(16, IntegerType::Modifier::Unsigned), TypeProvider::tvmcell()},
TypePointers{},
strings{string(), string(), string(), string(), string()},
strings{},
FunctionType::Kind::TVMTransfer,
false, StateMutability::Pure
));
members.emplace_back("setcode", TypeProvider::function(
TypePointers{TypeProvider::tvmcell()},
TypePointers{},
Expand Down Expand Up @@ -3875,14 +3836,6 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const
FunctionType::Kind::TVMHash,
false, StateMutability::Pure
));
members.emplace_back("hash", TypeProvider::function(
TypePointers{TypeProvider::array(DataLocation::Memory)},
TypePointers{TypeProvider::uint256()},
strings{string()},
strings{string()},
FunctionType::Kind::TVMHash,
false, StateMutability::Pure
));
members.emplace_back("hash", TypeProvider::function(
TypePointers{TypeProvider::array(DataLocation::Memory, true)},
TypePointers{TypeProvider::uint256()},
Expand Down Expand Up @@ -3994,6 +3947,17 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const
FunctionType::Kind::TVMDeploy,
true, StateMutability::Pure
));

members.emplace_back("deployAndCallConstructorWithFlag", TypeProvider::function(
TypePointers{TypeProvider::tvmcell(), TypeProvider::address(),
TypeProvider::uint(128), TypeProvider::uint(8), TypeProvider::uint(32)},
TypePointers{},
strings{string(), string(), string(), string(), string()},
strings{},
FunctionType::Kind::TVMDeploy,
true, StateMutability::Pure
));

members.emplace_back("functionId", TypeProvider::function(
TypePointers{},
TypePointers{TypeProvider::uint(32)},
Expand Down
2 changes: 1 addition & 1 deletion compiler/libsolidity/ast/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1417,7 +1417,7 @@ class MappingType: public Type

Category category() const override { return Category::Mapping; }

BoolResult isImplicitlyConvertibleTo(const MappingType * _other) const;
BoolResult isImplicitlyConvertibleTo(Type const& _other) const override;
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
std::string toString(bool _short) const override;
Expand Down
20 changes: 12 additions & 8 deletions compiler/libsolidity/codegen/TVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,19 @@ void TVMCompilerProceedContract(ContractDefinition const& _contract,
if (!TVMContractCompiler::m_optionsEnabled)
return;

std::string mainContract = (TVMContractCompiler::m_mainContractName == "") ?
std::string mainContract = (TVMContractCompiler::m_mainContractName.empty()) ?
getLastContractName() : TVMContractCompiler::m_mainContractName;

if (_contract.name() != mainContract)
return;
if (TVMContractCompiler::m_outputFolder.empty()) {
if (_contract.name() != mainContract)
return;
} else {
if (_contract.abstract() || _contract.isInterface())
return;
TVMContractCompiler::m_outputToFile = true;
namespace fs = boost::filesystem;
TVMContractCompiler::m_fileName = (fs::path(TVMContractCompiler::m_outputFolder) / _contract.name()).string();
}

for (ContractDefinition const* c : TVMContractCompiler::m_allContracts) {
TVMTypeChecker::check(c, *pragmaDirectives);
Expand Down Expand Up @@ -78,11 +86,7 @@ void TVMSetAllContracts(const std::vector<ContractDefinition const*>& allContrac
}

void TVMSetFileName(std::string _fileName) {
std::string fileName = _fileName;
if (auto point = fileName.find("."); point != std::string::npos)
fileName = fileName.substr(0, point);

TVMContractCompiler::m_fileName = fileName;
TVMContractCompiler::m_fileName = boost::filesystem::path(_fileName).stem().string();
}

bool TVMIsOutputProduced() {
Expand Down
Loading

0 comments on commit 382bada

Please sign in to comment.