From 6114cd8e8eaeeb7cb3c327bf1d5422b04a92ade3 Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Mon, 5 Oct 2020 12:21:30 +0200 Subject: [PATCH] Add missing annotation assignments --- Changelog.md | 1 + libsolidity/analysis/ImmutableValidator.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 11 ++++++++++- libsolidity/ast/ASTAnnotations.h | 3 ++- .../syntaxTests/lvalues/lvalue_not_set.sol | 11 +++++++++++ 5 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 test/libsolidity/syntaxTests/lvalues/lvalue_not_set.sol diff --git a/Changelog.md b/Changelog.md index 15e933f6c..3a77d42a3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ Compiler Features: Bugfixes: * Type Checker: Fix internal compiler error when calling `.push()` for a storage array with a nested mapping. * Type Checker: Add missing checks for calls using types incompatible with ABIEncoderV1 in modules where ABIEncoderV2 is not enabled. + * Fixed internal compiler errors for certain contracts involving the ``new`` expression ### 0.7.2 (2020-09-28) diff --git a/libsolidity/analysis/ImmutableValidator.cpp b/libsolidity/analysis/ImmutableValidator.cpp index 33f8cf170..5fdbd197b 100644 --- a/libsolidity/analysis/ImmutableValidator.cpp +++ b/libsolidity/analysis/ImmutableValidator.cpp @@ -167,7 +167,7 @@ void ImmutableValidator::analyseVariableReference(VariableDeclaration const& _va // If this is not an ordinary assignment, we write and read at the same time. bool write = _expression.annotation().willBeWrittenTo; - bool read = !_expression.annotation().willBeWrittenTo || !*_expression.annotation().lValueOfOrdinaryAssignment; + bool read = !_expression.annotation().willBeWrittenTo || !_expression.annotation().lValueOfOrdinaryAssignment; if (write) { if (!m_currentConstructor) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d8eef6119..8ed904129 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1420,7 +1420,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { requireLValue( *component, - *_tuple.annotation().lValueOfOrdinaryAssignment + _tuple.annotation().lValueOfOrdinaryAssignment ); types.push_back(type(*component)); } @@ -1534,6 +1534,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation) _operation.annotation().isConstant = false; _operation.annotation().isPure = !modifying && *_operation.subExpression().annotation().isPure; _operation.annotation().isLValue = false; + return false; } @@ -2391,6 +2392,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions) _functionCallOptions.annotation().isPure = false; _functionCallOptions.annotation().isConstant = false; + _functionCallOptions.annotation().isLValue = false; auto expressionFunctionType = dynamic_cast(type(_functionCallOptions.expression())); if (!expressionFunctionType) @@ -2523,6 +2525,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression) solAssert(!!type, "Type name not resolved."); _newExpression.annotation().isConstant = false; + _newExpression.annotation().isLValue = false; if (auto contractName = dynamic_cast(&_newExpression.typeName())) { @@ -2583,7 +2586,10 @@ void TypeChecker::endVisit(NewExpression const& _newExpression) _newExpression.annotation().isPure = true; } else + { + _newExpression.annotation().isPure = false; m_errorReporter.fatalTypeError(8807_error, _newExpression.location(), "Contract or array type expected."); + } } bool TypeChecker::visit(MemberAccess const& _memberAccess) @@ -2766,6 +2772,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ) annotation.isPure = *_memberAccess.expression().annotation().isPure; } + else + annotation.isLValue = false; } else if (exprType->category() == Type::Category::Module) { @@ -3061,6 +3069,7 @@ vector TypeChecker::cleanOverloadedDeclarations( bool TypeChecker::visit(Identifier const& _identifier) { IdentifierAnnotation& annotation = _identifier.annotation(); + if (!annotation.referencedDeclaration) { annotation.overloadedDeclarations = cleanOverloadedDeclarations(_identifier, annotation.candidateDeclarations); diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index f9770e0e6..0309e28db 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -253,7 +253,8 @@ struct ExpressionAnnotation: ASTAnnotation bool willBeWrittenTo = false; /// Whether the expression is an lvalue that is only assigned. /// Would be false for --, ++, delete, +=, -=, .... - SetOnce lValueOfOrdinaryAssignment; + /// Only relevant if isLvalue == true + bool lValueOfOrdinaryAssignment; /// Types and - if given - names of arguments if the expr. is a function /// that is called, used for overload resolution diff --git a/test/libsolidity/syntaxTests/lvalues/lvalue_not_set.sol b/test/libsolidity/syntaxTests/lvalues/lvalue_not_set.sol new file mode 100644 index 000000000..ab514ebc5 --- /dev/null +++ b/test/libsolidity/syntaxTests/lvalues/lvalue_not_set.sol @@ -0,0 +1,11 @@ +contract C { + function foo(uint x) public + { + // Used to cause an ICE + uint p = new uint[] = x; + } +} +// ---- +// TypeError 4247: (100-110): Expression has to be an lvalue. +// TypeError 7407: (113-114): Type uint256 is not implicitly convertible to expected type function (uint256) pure returns (uint256[] memory). +// TypeError 9574: (91-114): Type function (uint256) pure returns (uint256[] memory) is not implicitly convertible to expected type uint256.