Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.70.0 #140

Merged
merged 1 commit into from
Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
528 changes: 347 additions & 181 deletions API.md

Large diffs are not rendered by default.

237 changes: 127 additions & 110 deletions Cargo.lock

Large diffs are not rendered by default.

73 changes: 71 additions & 2 deletions Changelog_TON.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,76 @@
### 0.70.0 (2023-06-14)

Compiler features:
* Supported [inline assembly](./API.md#assembly).
* Supported overriding `onCodeUpgrade` function.
* Supported [User-defined Value Types](https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types). You can also use this type in public functions.
* [Supported `type(T).min` and `type(T).max`](API.md#type-information).
* New `<TvmBuilder>.store*()` functions:
* `<TvmBuilder>.storeIntLE2()`
* `<TvmBuilder>.storeIntLE4()`
* `<TvmBuilder>.storeIntLE8()`
* `<TvmBuilder>.storeUintLE2()`
* `<TvmBuilder>.storeUintLE4()`
* `<TvmBuilder>.storeUintLE8()`
* New `<TvmSlice>.load*()` functions:
* `<TvmSlice>.loadIntQ()`
* `<TvmSlice>.loadUintQ()`
* `<TvmSlice>.loadSliceQ()`
* `<TvmSlice>.loadIntLE2()`
* `<TvmSlice>.loadIntLE4()`
* `<TvmSlice>.loadIntLE8()`
* `<TvmSlice>.loadUintLE2()`
* `<TvmSlice>.loadUintLE4()`
* `<TvmSlice>.loadUintLE8()`
* `<TvmSlice>.loadIntLE4Q()`
* `<TvmSlice>.loadIntLE8Q()`
* `<TvmSlice>.loadUintLE4Q()`
* `<TvmSlice>.loadUintLE8Q()`
* New `<TvmSlice>.preload*()` functions:
* `<TvmSlice>.preload()`
* `<TvmSlice>.preloadQ()`
* `<TvmSlice>.preloadRef()`
* `<TvmSlice>.preloadInt()`
* `<TvmSlice>.preloadIntQ()`
* `<TvmSlice>.preloadUint()`
* `<TvmSlice>.preloadUintQ()`
* `<TvmSlice>.preloadSlice()`
* `<TvmSlice>.preloadSliceQ()`
* `<TvmSlice>.preloadIntLE4()`
* `<TvmSlice>.preloadIntLE8()`
* `<TvmSlice>.preloadUintLE4()`
* `<TvmSlice>.preloadUintLE8()`
* `<TvmSlice>.preloadIntLE4Q()`
* `<TvmSlice>.preloadIntLE8Q()`
* `<TvmSlice>.preloadUintLE4Q()`
* `<TvmSlice>.preloadUintLE8Q()`
* Supported `variable integer` type in arguments of `math.*` functions.
* Supported conversion `bytes`/`string` <=> `TvmSlice`.

Gas optimizations:
* Assorted stack optimizations.

Bugfixes:
* Fixed compilation fail if you use `<TvmSlice>.loadSlice(l)` where `l` is constant and `l == 0` or `l > 256`.

Other changes:
* Renamed some functions. Old functions are available and marked as deprecated. Renaming:
* `<TvmSlice>.decode()` -> `<TvmSlice>.load()`
* `<TvmSlice>.decodeQ()` -> `<TvmSlice>.loadQ()`
* `<TvmSlice>.decodeFunctionParams()` -> `<TvmSlice>.loadFunctionParams()`
* `<TvmSlice>.decodeStateVars()` -> `<TvmSlice>.loadStateVars()`
* `<TvmSlice>.loadSigned()` -> `<TvmSlice>.loadInt()`
* `<TvmSlice>.loadUnsigned()` -> `<TvmSlice>.loadUint()`
* `<TvmBuilder>.storeSigned()` -> `<TvmSlice>.storeInt()`
* `<TvmBuilder>.storeUnsigned()` -> `<TvmSlice>.storeUint()`
* Improved `try-catch` (experimental feature).
* Now `tx.storageFee` returns `uint120` (not `uint64`).
* Renamed `tx.timestamp` to `tx.logicaltime`. `tx.timestamp` is available and marked as deprecated.

### 0.69.0 (2023-05-15)

Breaking changes:
* `pragma AbiHeader time` is no longer allowed for use. Timestamp in header of external message is enabled by default and can be disabled with `pragma AbiHeader notime`.
* `pragma AbiHeader time` is no longer allowed for use. Timestamp in header of external message is enabled by default and can be disabled with `pragma AbiHeader notime`.

Compiler features:
* Supported generating code for The Open Network. Use command line option `--tvm-version ton`. We don't use `ZERO(SWAP|ROTR)IF[NOT][2]`, `COPYLEFT`, `INITCODEHASH`, `MYCODE`, `STORAGEFEE`, `LDCONT`, `STCONT` and another opcodes for ton.
Expand All @@ -10,7 +79,7 @@ Optimizations:
* Improved constant analyzer that compile more optimal code for `require`/`revert` functions and another cases.

Bugfixes:
* Fixed segmentation fault that could occur in some cases of using `var[U]Int` types.
* Fixed segmentation fault that could occur in some cases of using `variable integer` types.
* Fixed segmentation fault that occurred in constructions `optional(T1, T2) x = null;` and some another cases.

### 0.68.0 (2023-04-19)
Expand Down
2 changes: 1 addition & 1 deletion compiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ include(EthPolicy)
eth_policy()

# project name and version should be set after cmake_policy CMP0048
set(PROJECT_VERSION "0.69.0")
set(PROJECT_VERSION "0.70.0")
# OSX target needed in order to support std::visit
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
Expand Down
7 changes: 3 additions & 4 deletions compiler/libsolidity/analysis/ControlFlowBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,9 @@ bool ControlFlowBuilder::visit(Conditional const& _conditional)

bool ControlFlowBuilder::visit(TryStatement const& _tryStatement)
{
appendControlFlow(_tryStatement.body());

auto nodes = splitFlow(1);
nodes[0] = createFlow(nodes[0], _tryStatement.clause().block());
auto nodes = splitFlow(2);
nodes[0] = createFlow(nodes[0], _tryStatement.body());
nodes[1] = createFlow(nodes[1], _tryStatement.clause());
mergeFlow(nodes);

return false;
Expand Down
21 changes: 12 additions & 9 deletions compiler/libsolidity/analysis/StaticAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,23 @@ bool StaticAnalyzer::visit(FunctionDefinition const& _function)
return true;
}

void StaticAnalyzer::endVisit(FunctionDefinition const&)
void StaticAnalyzer::endVisit(FunctionDefinition const& _funDefinition)
{
if (m_currentFunction && !m_currentFunction->body().statements().empty())
for (auto const& var: m_localVarUseCount)
if (var.second == 0)
{
if (var.first.second->isCallableOrCatchParameter())
m_errorReporter.warning(
5667_error,
var.first.second->location(),
"Unused " +
string(var.first.second->isTryCatchParameter() ? "try/catch" : "function") +
" parameter. Remove or comment out the variable name to silence this warning."
);
if (var.first.second->isCallableOrCatchParameter()) {
if (!_funDefinition.isInlineAssembly()) {
m_errorReporter.warning(
5667_error,
var.first.second->location(),
"Unused " +
string(var.first.second->isTryCatchParameter() ? "try/catch" : "function") +
" parameter. Remove or comment out the variable name to silence this warning."
);
}
}
else
m_errorReporter.warning(2072_error, var.first.second->location(), "Unused local variable.");
}
Expand Down
39 changes: 25 additions & 14 deletions compiler/libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ TypePointers TypeChecker::typeCheckMetaTypeFunctionAndRetrieveReturnType(Functio
wrongType = contractType->isSuper();
else if (
typeCategory != Type::Category::Integer &&
typeCategory != Type::Category::VarInteger &&
typeCategory != Type::Category::Enum
)
wrongType = true;
Expand Down Expand Up @@ -719,6 +720,14 @@ bool TypeChecker::isBadAbiType(
case Type::Category::VarInteger:
break;

case Type::Category::UserDefinedValueType: {
auto userDefType = dynamic_cast<UserDefinedValueType const*>(curType);
if (isBadAbiType(origVarLoc, &userDefType->underlyingType(), curVarLoc, usedStructs, doPrintErr)) {
return true;
}
break;
}

default: {
printError("ABI doesn't support " + curType->toString() + " type.");
return true;
Expand Down Expand Up @@ -757,8 +766,8 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
if (!_function.modifiers().empty() && _function.isFree())
m_errorReporter.syntaxError(5811_error, _function.location(), "Free functions cannot have modifiers.");

if (_function.externalMsg() || _function.internalMsg()) {
if (_function.externalMsg() && _function.internalMsg()) {
if (_function.isExternalMsg() || _function.isInternalMsg()) {
if (_function.isExternalMsg() && _function.isInternalMsg()) {
m_errorReporter.typeError(228_error, _function.location(), R"("internalMsg" and "externalMsg" cannot be used together.)");
}
if (!_function.functionIsExternallyVisible()) {
Expand Down Expand Up @@ -1152,9 +1161,9 @@ void TypeChecker::endVisit(TryStatement const& _tryStatement)

auto printError = [&](SourceLocation const& loc){
m_errorReporter.typeError(
228_error,
loc,
"Expected `catch (variant value, uint number) { ... }`.");
228_error,
loc,
"Expected `catch (variant value, uint number) { ... }`.");
};
if (errArgs.size() != 2) {
printError(clause.location());
Expand All @@ -1163,7 +1172,7 @@ void TypeChecker::endVisit(TryStatement const& _tryStatement)
if (*errArgs.at(0)->type() != *TypeProvider::variant()) {
printError(errArgs.at(0)->location());
}
if (*errArgs.at(1)->type() != *TypeProvider::uint256()) {
if (*errArgs.at(1)->type() != *TypeProvider::uint(16)) {
printError(errArgs.at(1)->location());
}
}
Expand Down Expand Up @@ -3350,11 +3359,11 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)

for (const auto & arg : arguments) {
Type::Category cat = arg->annotation().type->mobileType()->category();
if (cat != Type::Category::Integer) {
if (cat != Type::Category::Integer && cat != Type::Category::VarInteger) {
m_errorReporter.fatalTypeError(
228_error,
arg->location(),
"Expected an integer type."
"Expected an integer or variable integer type."
);
}
}
Expand All @@ -3376,11 +3385,11 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)

for (const auto & arg : arguments) {
Type::Category cat = arg->annotation().type->mobileType()->category();
if (cat != Type::Category::Integer && cat != Type::Category::FixedPoint) {
if (cat != Type::Category::Integer && cat != Type::Category::FixedPoint && cat != Type::Category::VarInteger) {
m_errorReporter.fatalTypeError(
228_error,
arg->location(),
"Expected integer or fixed point type."
"Expected integer, variable integer or fixed point type."
);
}
}
Expand Down Expand Up @@ -3491,13 +3500,15 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
returnTypes = checkSliceDecode(arguments);
break;
}
case FunctionType::Kind::TVMSliceDecode:
case FunctionType::Kind::TVMSliceLoad:
case FunctionType::Kind::TVMSlicePreload:
{
checkAtLeastOneArg();
returnTypes = checkSliceDecode(_functionCall.arguments());
break;
}
case FunctionType::Kind::TVMSliceDecodeQ:
case FunctionType::Kind::TVMSliceLoadQ:
case FunctionType::Kind::TVMSlicePreloadQ:
{
checkAtLeastOneArg();
TypePointers members = checkSliceDecode(_functionCall.arguments()); // TODO make for Q
Expand All @@ -3512,7 +3523,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
returnTypes = getReturnTypesForTVMConfig(_functionCall);
break;
}
case FunctionType::Kind::DecodeFunctionParams:
case FunctionType::Kind::TVMSliceLoadFunctionParams:
{
if (arguments.size() != 1) {
m_errorReporter.fatalTypeError(
Expand Down Expand Up @@ -3563,7 +3574,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
returnTypes = functionType->returnParameterTypes();
break;
}
case FunctionType::Kind::TVMSliceDecodeStateVars:
case FunctionType::Kind::TVMSliceLoadStateVars:
{
if (arguments.size() != 1) {
m_errorReporter.fatalTypeError(
Expand Down
8 changes: 5 additions & 3 deletions compiler/libsolidity/analysis/ViewPureChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ bool ViewPureChecker::visit(FunctionDefinition const& _funDef)
"Library functions must have default mutability. Delete keyword view or pure.");
}
}
if (_funDef.isFree() && _funDef.stateMutability() != StateMutability::NonPayable) {
if (_funDef.isFree() && !_funDef.isInlineAssembly() && _funDef.stateMutability() != StateMutability::NonPayable) {
m_errorReporter.warning(228_error, _funDef.location(),
"Free functions must have default mutability. Delete keyword view or pure.");
}
Expand Down Expand Up @@ -82,7 +82,8 @@ void ViewPureChecker::endVisit(FunctionDefinition const& _funDef)
!_funDef.isFree() &&
!_funDef.isFallback() &&
!_funDef.isReceive() &&
!_funDef.virtualSemantics()
!_funDef.virtualSemantics() &&
!_funDef.isInlineAssembly()
)
m_errorReporter.warning(
2018_error,
Expand Down Expand Up @@ -264,7 +265,7 @@ void ViewPureChecker::endVisit(FunctionCall const& _functionCall)
auto ident = dynamic_cast<Identifier const*>(&_functionCall.expression());
if (ident) {
auto funcDef = dynamic_cast<FunctionDefinition const*>(ident->annotation().referencedDeclaration);
isFree = funcDef && funcDef->isFree();
isFree = funcDef && funcDef->isFree() && !funcDef->isInlineAssembly();
}
if (isFree)
mutability = StateMutability::Pure;
Expand Down Expand Up @@ -412,6 +413,7 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
{MagicType::Kind::TVM, "setGasLimit"},
{MagicType::Kind::TVM, "setcode"},
{MagicType::Kind::TVM, "stateInitHash"},
{MagicType::Kind::Transaction, "logicaltime"},
{MagicType::Kind::Transaction, "storageFee"},
{MagicType::Kind::Transaction, "timestamp"},
};
Expand Down
5 changes: 5 additions & 0 deletions compiler/libsolidity/ast/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,11 @@ StatementAnnotation& Statement::annotation() const
return initAnnotation<StatementAnnotation>();
}

StatementAnnotation& FreeInlineAssembly::annotation() const
{
return initAnnotation<StatementAnnotation>();
}

InlineAssemblyAnnotation& InlineAssembly::annotation() const
{
return initAnnotation<InlineAssemblyAnnotation>();
Expand Down
43 changes: 32 additions & 11 deletions compiler/libsolidity/ast/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -930,11 +930,12 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen
std::vector<ASTPointer<ModifierInvocation>> _modifiers,
ASTPointer<ParameterList> const& _returnParameters,
ASTPointer<Block> const& _body,
std::optional<uint32_t> _functionID = {},
bool _isInline = false,
bool _responsible = false,
bool _externalMsg = false,
bool _internalMsg = false
std::optional<uint32_t> _functionID,
bool _isInline,
bool _responsible,
bool _externalMsg,
bool _internalMsg,
bool _freeInlineAssembly
):
CallableDeclaration(_id, _location, _name, std::move(_nameLocation), _visibility, _parameters, _isVirtual, _overrides, _returnParameters),
StructurallyDocumented(_documentation),
Expand All @@ -945,10 +946,11 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen
m_functionModifiers(std::move(_modifiers)),
m_body(_body),
m_functionID(_functionID),
m_isInline(_isInline),
m_inline(_isInline),
m_responsible{_responsible},
m_externalMsg{_externalMsg},
m_internalMsg{_internalMsg}
m_internalMsg{_internalMsg},
m_inlineAssembly{_freeInlineAssembly}
{
solAssert(_kind == Token::Constructor || _kind == Token::Function ||
_kind == Token::Fallback || _kind == Token::Receive || _kind == Token::onBounce ||
Expand Down Expand Up @@ -1015,10 +1017,11 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen
}

std::optional<uint32_t> functionID() const { return m_functionID; }
bool isInline() const { return m_isInline; }
bool isInline() const { return m_inline; }
bool isResponsible() const { return m_responsible; }
bool externalMsg() const { return m_externalMsg; }
bool internalMsg() const { return m_internalMsg; }
bool isExternalMsg() const { return m_externalMsg; }
bool isInternalMsg() const { return m_internalMsg; }
bool isInlineAssembly() const { return m_inlineAssembly; }
FunctionDefinition const& resolveVirtual(
ContractDefinition const& _mostDerivedContract,
ContractDefinition const* _searchStart = nullptr
Expand All @@ -1031,10 +1034,11 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen
std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers;
ASTPointer<Block> m_body;
std::optional<uint32_t> m_functionID;
bool m_isInline;
bool m_inline{};
bool m_responsible{};
bool m_externalMsg{};
bool m_internalMsg{};
bool m_inlineAssembly{};
};

/**
Expand Down Expand Up @@ -1558,6 +1562,23 @@ class Statement: public ASTNode, public Documented
StatementAnnotation& annotation() const override;
};

class FreeInlineAssembly: public Statement
{
public:
explicit FreeInlineAssembly(
int64_t _id,
SourceLocation const& _location,
ASTPointer<ASTString> const& _docString,
std::vector<ASTPointer<Expression>> _lines
): Statement(_id, _location, _docString), m_lines{_lines} {}
void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override;
StatementAnnotation& annotation() const override;
std::vector<ASTPointer<Expression>> const& lines() const { return m_lines; }
private:
std::vector<ASTPointer<Expression>> m_lines;
};

/**
* Inline assembly.
*/
Expand Down
Loading