diff --git a/Changelog.md b/Changelog.md index 71ccea0df..f30a2cb5f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Compiler Features: Bugfixes: + * Immutables: Disallow initialization of immutables in for loops and ternary expressions. * SMTChecker: Fix encoding of side-effects inside ``if`` and ``ternary conditional``statements in the BMC engine. diff --git a/libsolidity/analysis/ImmutableValidator.cpp b/libsolidity/analysis/ImmutableValidator.cpp index 8e89c49ab..7ba3b6afa 100644 --- a/libsolidity/analysis/ImmutableValidator.cpp +++ b/libsolidity/analysis/ImmutableValidator.cpp @@ -73,6 +73,16 @@ bool ImmutableValidator::visit(Assignment const& _assignment) return false; } +bool ImmutableValidator::visit(Conditional const& _conditional) +{ + ScopedSaveAndRestore branchGuard{m_inBranch, true}; + + _conditional.condition().accept(*this); + _conditional.trueExpression().accept(*this); + _conditional.falseExpression().accept(*this); + + return false; +} bool ImmutableValidator::visit(FunctionDefinition const& _functionDefinition) { @@ -132,6 +142,21 @@ bool ImmutableValidator::visit(WhileStatement const& _whileStatement) return false; } +bool ImmutableValidator::visit(ForStatement const& _forStatement) +{ + ScopedSaveAndRestore forLoopGuard{m_inLoop, true}; + + if (auto&& initializationExpression = _forStatement.initializationExpression()) + initializationExpression->accept(*this); + if (auto&& condition = _forStatement.condition()) + condition->accept(*this); + if (auto&& loopExpression = _forStatement.loopExpression()) + loopExpression->accept(*this); + _forStatement.body().accept(*this); + + return false; +} + bool ImmutableValidator::visit(TryStatement const& _tryStatement) { ScopedSaveAndRestore constructorGuard{m_inTryStatement, true}; @@ -228,7 +253,7 @@ void ImmutableValidator::analyseVariableReference(VariableDeclaration const& _va m_errorReporter.typeError( 4599_error, _expression.location(), - "Cannot write to immutable here: Immutable variables cannot be initialized inside an if statement." + "Cannot write to immutable here: Immutable variables cannot be initialized inside a conditional (if/ternary) statement." ); else if (m_inTryStatement) m_errorReporter.typeError( diff --git a/libsolidity/analysis/ImmutableValidator.h b/libsolidity/analysis/ImmutableValidator.h index 43a4b5dbf..0db2c1893 100644 --- a/libsolidity/analysis/ImmutableValidator.h +++ b/libsolidity/analysis/ImmutableValidator.h @@ -50,11 +50,13 @@ public: private: bool visit(Assignment const& _assignment); + bool visit(Conditional const& _conditional); bool visit(FunctionDefinition const& _functionDefinition); bool visit(ModifierDefinition const& _modifierDefinition); bool visit(MemberAccess const& _memberAccess); bool visit(IfStatement const& _ifStatement); bool visit(WhileStatement const& _whileStatement); + bool visit(ForStatement const& _forStatement); bool visit(TryStatement const& _tryStatement); void endVisit(IdentifierPath const& _identifierPath); void endVisit(Identifier const& _identifier); diff --git a/test/libsolidity/syntaxTests/immutable/conditionally_initialized.sol b/test/libsolidity/syntaxTests/immutable/conditionally_initialized.sol index 052a1b597..616351ada 100644 --- a/test/libsolidity/syntaxTests/immutable/conditionally_initialized.sol +++ b/test/libsolidity/syntaxTests/immutable/conditionally_initialized.sol @@ -6,4 +6,4 @@ contract C { } } // ---- -// TypeError 4599: (86-87): Cannot write to immutable here: Immutable variables cannot be initialized inside an if statement. +// TypeError 4599: (86-87): Cannot write to immutable here: Immutable variables cannot be initialized inside a conditional (if/ternary) statement. diff --git a/test/libsolidity/syntaxTests/immutable/for_loop_initialized.sol b/test/libsolidity/syntaxTests/immutable/for_loop_initialized.sol new file mode 100644 index 000000000..c19b874da --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/for_loop_initialized.sol @@ -0,0 +1,12 @@ +contract C { + uint immutable x; + constructor() { + for (x = 1; x < 10; ++x) + x = 5; + } +} + +// ---- +// TypeError 6672: (68-69): Cannot write to immutable here: Immutable variables cannot be initialized inside a loop. +// TypeError 6672: (85-86): Cannot write to immutable here: Immutable variables cannot be initialized inside a loop. +// TypeError 6672: (100-101): Cannot write to immutable here: Immutable variables cannot be initialized inside a loop. diff --git a/test/libsolidity/syntaxTests/immutable/ternary_initialized.sol b/test/libsolidity/syntaxTests/immutable/ternary_initialized.sol new file mode 100644 index 000000000..b16d99646 --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/ternary_initialized.sol @@ -0,0 +1,15 @@ +contract A +{ + uint256 immutable x; + uint256 y = 0; + + constructor(bool _branch) + { + _branch ? x = 1 : y = 2; + _branch ? y = 3 : x = 4; + } +} + +// ---- +// TypeError 4599: (112-113): Cannot write to immutable here: Immutable variables cannot be initialized inside a conditional (if/ternary) statement. +// TypeError 4599: (153-154): Cannot write to immutable here: Immutable variables cannot be initialized inside a conditional (if/ternary) statement.