diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/analysis/SyntaxChecker.cpp | 10 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 38 | ||||
-rw-r--r-- | libsolidity/ast/AST.h | 16 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 20 |
4 files changed, 19 insertions, 65 deletions
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index cd0dc2a4..63f8fac3 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -192,15 +192,9 @@ bool SyntaxChecker::visit(Throw const& _throwStatement) bool SyntaxChecker::visit(UnaryOperation const& _operation) { - bool const v050 = m_sourceUnit->annotation().experimentalFeatures.count(ExperimentalFeature::V050); - if (_operation.getOperator() == Token::Add) - { - if (v050) - m_errorReporter.syntaxError(_operation.location(), "Use of unary + is deprecated."); - else - m_errorReporter.warning(_operation.location(), "Use of unary + is deprecated."); - } + m_errorReporter.syntaxError(_operation.location(), "Use of unary + is disallowed."); + return true; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 5ad5be4f..b631bd1e 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1073,10 +1073,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) if (varDecl.referenceLocation() == VariableDeclaration::Location::Default) errorText += " Did you mean '<type> memory " + varDecl.name() + "'?"; solAssert(m_scope, ""); - if (v050) - m_errorReporter.declarationError(varDecl.location(), errorText); - else - m_errorReporter.warning(varDecl.location(), errorText); + m_errorReporter.declarationError(varDecl.location(), errorText); } } else if (dynamic_cast<MappingType const*>(type(varDecl).get())) @@ -1337,7 +1334,6 @@ bool TypeChecker::visit(Conditional const& _conditional) bool TypeChecker::visit(Assignment const& _assignment) { - bool const v050 = m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050); requireLValue(_assignment.leftHandSide()); TypePointer t = type(_assignment.leftHandSide()); _assignment.annotation().type = t; @@ -1354,25 +1350,8 @@ bool TypeChecker::visit(Assignment const& _assignment) expectType(_assignment.rightHandSide(), *tupleType); // expectType does not cause fatal errors, so we have to check again here. - if (TupleType const* rhsType = dynamic_cast<TupleType const*>(type(_assignment.rightHandSide()).get())) - { + if (dynamic_cast<TupleType const*>(type(_assignment.rightHandSide()).get())) checkDoubleStorageAssignment(_assignment); - // @todo For 0.5.0, this code shoud move to TupleType::isImplicitlyConvertibleTo, - // but we cannot do it right now. - if (rhsType->components().size() != tupleType->components().size()) - { - string message = - "Different number of components on the left hand side (" + - toString(tupleType->components().size()) + - ") than on the right hand side (" + - toString(rhsType->components().size()) + - ")."; - if (v050) - m_errorReporter.typeError(_assignment.location(), message); - else - m_errorReporter.warning(_assignment.location(), message); - } - } } else if (t->category() == Type::Category::Mapping) { @@ -1429,14 +1408,12 @@ bool TypeChecker::visit(TupleExpression const& _tuple) } else { - bool const v050 = m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050); bool isPure = true; TypePointer inlineArrayType; for (size_t i = 0; i < components.size(); ++i) { - // Outside of an lvalue-context, the only situation where a component can be empty is (x,). - if (!components[i] && !(i == 1 && components.size() == 2)) + if (!components[i]) m_errorReporter.fatalTypeError(_tuple.location(), "Tuple component cannot be empty."); else if (components[i]) { @@ -1448,10 +1425,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { if (_tuple.isInlineArray()) m_errorReporter.fatalTypeError(components[i]->location(), "Array component cannot be empty."); - if (v050) - m_errorReporter.fatalTypeError(components[i]->location(), "Tuple component cannot be empty."); - else - m_errorReporter.warning(components[i]->location(), "Tuple component cannot be empty."); + m_errorReporter.typeError(components[i]->location(), "Tuple component cannot be empty."); } // Note: code generation will visit each of the expression even if they are not assigned from. @@ -1489,11 +1463,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) if (components.size() == 1) _tuple.annotation().type = type(*components[0]); else - { - if (components.size() == 2 && !components[1]) - types.pop_back(); _tuple.annotation().type = make_shared<TupleType>(types); - } } } diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index d703ae53..9906fa68 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1250,13 +1250,12 @@ private: }; /** - * Definition of a variable as a statement inside a function. It requires a type name (which can - * also be "var") but the actual assignment can be missing. - * Examples: var a = 2; uint256 a; - * As a second form, multiple variables can be declared, cannot have a type and must be assigned - * right away. If the first or last component is unnamed, it can "consume" an arbitrary number - * of components. - * Examples: var (a, b) = f(); var (a,,,c) = g(); var (a,) = d(); + * Definition of one or more variables as a statement inside a function. + * If multiple variables are declared, a value has to be assigned directly. + * If only a single variable is declared, the value can be missing. + * Examples: + * uint[] memory a; uint a = 2; + * (uint a, bytes32 b, ) = f(); (, uint a, , StructName storage x) = g(); */ class VariableDeclarationStatement: public Statement { @@ -1278,6 +1277,9 @@ public: private: /// List of variables, some of which can be empty pointers (unnamed components). + /// Note that the ``m_value`` member of these is unused. Instead, ``m_initialValue`` + /// below is used, because the initial value can be a single expression assigned + /// to all variables. std::vector<ASTPointer<VariableDeclaration>> m_variables; /// The assigned expression / initial value. ASTPointer<Expression> m_initialValue; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 1c4eb76e..23614e58 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2238,25 +2238,13 @@ bool TupleType::isImplicitlyConvertibleTo(Type const& _other) const TypePointers const& targets = tupleType->components(); if (targets.empty()) return components().empty(); - if (components().size() != targets.size() && !targets.front() && !targets.back()) - return false; // (,a,) = (1,2,3,4) - unable to position `a` in the tuple. - size_t minNumValues = targets.size(); - if (!targets.back() || !targets.front()) - --minNumValues; // wildcards can also match 0 components - if (components().size() < minNumValues) + if (components().size() != targets.size()) return false; - if (components().size() > targets.size() && targets.front() && targets.back()) - return false; // larger source and no wildcard - bool fillRight = !targets.back() || targets.front(); - for (size_t i = 0; i < min(targets.size(), components().size()); ++i) - { - auto const& s = components()[fillRight ? i : components().size() - i - 1]; - auto const& t = targets[fillRight ? i : targets.size() - i - 1]; - if (!s && t) + for (size_t i = 0; i < targets.size(); ++i) + if (!components()[i] && targets[i]) return false; - else if (s && t && !s->isImplicitlyConvertibleTo(*t)) + else if (components()[i] && targets[i] && !components()[i]->isImplicitlyConvertibleTo(*targets[i])) return false; - } return true; } else |