From 5cfe0b7670528aacce499bedaf2228074bc075fc Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 4 Sep 2019 17:45:12 +0200 Subject: [PATCH] Allow explicit conversion from address to address payable --- Changelog.md | 1 + docs/060-breaking-changes.rst | 2 + docs/types/conversion.rst | 2 + docs/types/value-types.rst | 18 +++--- libsolidity/analysis/TypeChecker.cpp | 15 +++-- libsolidity/ast/AST.h | 15 +++-- libsolidity/ast/ASTJsonConverter.cpp | 2 +- libsolidity/ast/TypeProvider.cpp | 9 ++- libsolidity/ast/TypeProvider.h | 2 +- libsolidity/ast/Types.cpp | 4 +- libsolidity/parsing/Parser.cpp | 25 +++++++-- test/libsolidity/ASTJSON/address_payable.json | 56 +++++++++---------- .../ASTJSON/address_payable_legacy.json | 54 +++++++++--------- .../ASTJSON/long_type_name_identifier.json | 32 +++++------ .../long_type_name_identifier_legacy.json | 32 +++++------ test/libsolidity/ASTJSON/short_type_name.json | 28 +++++----- .../ASTJSON/short_type_name_legacy.json | 28 +++++----- .../ASTJSON/short_type_name_ref.json | 30 +++++----- .../ASTJSON/short_type_name_ref_legacy.json | 30 +++++----- ...explicit_conversion_address_to_payable.sol | 11 ++++ .../explicit_conversion_sender_to_payable.sol | 9 +++ .../explicit_conversion_this_to_payable.sol | 8 +++ .../parsing/payable_without_arguments.sol | 7 +++ 23 files changed, 248 insertions(+), 172 deletions(-) create mode 100644 test/libsolidity/syntaxTests/conversion/explicit_conversion_address_to_payable.sol create mode 100644 test/libsolidity/syntaxTests/conversion/explicit_conversion_sender_to_payable.sol create mode 100644 test/libsolidity/syntaxTests/conversion/explicit_conversion_this_to_payable.sol create mode 100644 test/libsolidity/syntaxTests/parsing/payable_without_arguments.sol diff --git a/Changelog.md b/Changelog.md index 2b1022926..0817154cc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Breaking changes: Language Features: * Allow global enums and structs. * Allow underscores as delimiters in hex strings. + * Allow explicit conversions from ``address`` to ``address payable`` via ``payable(...)``. Compiler Features: diff --git a/docs/060-breaking-changes.rst b/docs/060-breaking-changes.rst index 173c05901..79cc268de 100644 --- a/docs/060-breaking-changes.rst +++ b/docs/060-breaking-changes.rst @@ -16,6 +16,8 @@ This section lists purely syntactic changes that do not affect the behavior of e * Conversions from external function types to ``address`` are now disallowed. Instead external function types have a member called ``address``, similar to the existing ``selector`` member. +* Conversions from ``address`` to ``address payable`` are now possible via ``payable(x)``, where + ``x`` must be of type ``address``. * New reserved keywords: ``virtual``. diff --git a/docs/types/conversion.rst b/docs/types/conversion.rst index 51e373405..b2bf088bd 100644 --- a/docs/types/conversion.rst +++ b/docs/types/conversion.rst @@ -128,3 +128,5 @@ As described in :ref:`address_literals`, hex literals of the correct size that p test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type. Explicit conversions from ``bytes20`` or any integer type to ``address`` result in ``address payable``. + +An ``address a`` can be converted to ``address payable`` via ``payable(a)``. diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 68782027d..f8c461c73 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -171,18 +171,20 @@ while a plain ``address`` cannot be sent Ether. Type conversions: -Implicit conversions from ``address payable`` to ``address`` are allowed, whereas conversions from ``address`` to ``address payable`` are -not possible (the only way to perform such a conversion is by using an intermediate conversion to ``uint160``). +Implicit conversions from ``address payable`` to ``address`` are allowed, whereas conversions from ``address`` to ``address payable`` +must be explicit via ``payable(
)``. :ref:`Address literals` can be implicitly converted to ``address payable``. Explicit conversions to and from ``address`` are allowed for integers, integer literals, ``bytes20`` and contract types with the following caveat: -Conversions of the form ``address payable(x)`` are not allowed. Instead the result of a conversion of the form ``address(x)`` +The result of a conversion of the form ``address(x)`` has the type ``address payable``, if ``x`` is of integer or fixed bytes type, a literal or a contract with a payable fallback function. If ``x`` is a contract without payable fallback function, then ``address(x)`` will be of type ``address``. In external function signatures ``address`` is used for both the ``address`` and the ``address payable`` type. +Only expressions of type ``address`` can be converted to type ``address payable`` via ``payable(
)``. + .. note:: It might very well be that you do not need to care about the distinction between ``address`` and ``address payable`` and just use ``address`` everywhere. For example, @@ -310,10 +312,12 @@ Every :ref:`contract` defines its own type. You can implicitly convert contracts to contracts they inherit from. Contracts can be explicitly converted to and from the ``address`` type. -Explicit conversion to and from the ``address payable`` type -is only possible if the contract type has a payable fallback function. -The conversion is still performed using ``address(x)`` and not -using ``address payable(x)``. You can find more information in the section about +Explicit conversion to and from the ``address payable`` type is only possible +if the contract type has a payable fallback function. The conversion is still +performed using ``address(x)``. If the contract type does not have a payable +fallback function, the conversion to ``address payable`` can be done using +``payable(address(x))``. +You can find more information in the section about the :ref:`address type
`. .. note:: diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e0f833493..d1faa6882 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1527,11 +1527,14 @@ TypePointer TypeChecker::typeCheckTypeConversionAndRetrieveReturnType( "\"." ); } - if (resultType->category() == Type::Category::Address) - { - bool const payable = argType->isExplicitlyConvertibleTo(*TypeProvider::payableAddress()); - resultType = payable ? TypeProvider::payableAddress() : TypeProvider::address(); - } + if (auto addressType = dynamic_cast(resultType)) + if (addressType->stateMutability() != StateMutability::Payable) + { + bool payable = false; + if (argType->category() != Type::Category::Address) + payable = argType->isExplicitlyConvertibleTo(*TypeProvider::payableAddress()); + resultType = payable ? TypeProvider::payableAddress() : TypeProvider::address(); + } } return resultType; } @@ -2423,7 +2426,7 @@ bool TypeChecker::visit(Identifier const& _identifier) void TypeChecker::endVisit(ElementaryTypeNameExpression const& _expr) { - _expr.annotation().type = TypeProvider::typeType(TypeProvider::fromElementaryTypeName(_expr.typeName())); + _expr.annotation().type = TypeProvider::typeType(TypeProvider::fromElementaryTypeName(_expr.type().typeName(), _expr.type().stateMutability())); _expr.annotation().isPure = true; } diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 764a5d9fe..e808003ec 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1682,16 +1682,21 @@ private: class ElementaryTypeNameExpression: public PrimaryExpression { public: - ElementaryTypeNameExpression(SourceLocation const& _location, ElementaryTypeNameToken const& _type): - PrimaryExpression(_location), m_typeToken(_type) - {} + ElementaryTypeNameExpression( + SourceLocation const& _location, + ASTPointer const& _type + ): + PrimaryExpression(_location), + m_type(_type) + { + } void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; - ElementaryTypeNameToken const& typeName() const { return m_typeToken; } + ElementaryTypeName const& type() const { return *m_type; } private: - ElementaryTypeNameToken m_typeToken; + ASTPointer m_type; }; /** diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index a81ec3ac9..c6f7ecf9b 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -712,7 +712,7 @@ bool ASTJsonConverter::visit(Identifier const& _node) bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node) { std::vector> attributes = { - make_pair(m_legacy ? "value" : "typeName", _node.typeName().toString()) + make_pair(m_legacy ? "value" : "typeName", _node.type().typeName().toString()) }; appendExpressionAttributes(attributes, _node.annotation()); setJsonNode(_node, "ElementaryTypeNameExpression", std::move(attributes)); diff --git a/libsolidity/ast/TypeProvider.cpp b/libsolidity/ast/TypeProvider.cpp index 6e94c011b..7d7824da3 100644 --- a/libsolidity/ast/TypeProvider.cpp +++ b/libsolidity/ast/TypeProvider.cpp @@ -200,7 +200,7 @@ inline T const* TypeProvider::createAndGet(Args&& ... _args) return static_cast(instance().m_generalTypes.back().get()); } -Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const& _type) +Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const& _type, boost::optional _stateMutability) { solAssert( TokenTraits::isElementaryTypeName(_type.token()), @@ -233,7 +233,14 @@ Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const& case Token::UFixed: return fixedPoint(128, 18, FixedPointType::Modifier::Unsigned); case Token::Address: + { + if (_stateMutability) + { + solAssert(*_stateMutability == StateMutability::Payable, ""); + return payableAddress(); + } return address(); + } case Token::Bool: return boolean(); case Token::Bytes: diff --git a/libsolidity/ast/TypeProvider.h b/libsolidity/ast/TypeProvider.h index 4b18f52e6..f6f4e1f74 100644 --- a/libsolidity/ast/TypeProvider.h +++ b/libsolidity/ast/TypeProvider.h @@ -54,7 +54,7 @@ public: /// @name Factory functions /// Factory functions that convert an AST @ref TypeName to a Type. - static Type const* fromElementaryTypeName(ElementaryTypeNameToken const& _type); + static Type const* fromElementaryTypeName(ElementaryTypeNameToken const& _type, boost::optional _stateMutability = {}); /// Converts a given elementary type name with optional data location /// suffix " storage", " calldata" or " memory" to a type pointer. If suffix not given, defaults to " storage". diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 30323c316..79d41bfe9 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -412,7 +412,9 @@ BoolResult AddressType::isImplicitlyConvertibleTo(Type const& _other) const BoolResult AddressType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - if (auto const* contractType = dynamic_cast(&_convertTo)) + if (_convertTo.category() == category()) + return true; + else if (auto const* contractType = dynamic_cast(&_convertTo)) return (m_stateMutability >= StateMutability::Payable) || !contractType->isPayable(); return isImplicitlyConvertibleTo(_convertTo) || _convertTo.category() == Category::Integer || diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 1945a07dc..14c4a29fc 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1585,6 +1585,17 @@ ASTPointer Parser::parseLeftHandSideExpression( nodeFactory.markEndPosition(); expression = nodeFactory.createNode(typeName); } + else if (m_scanner->currentToken() == Token::Payable) + { + expectToken(Token::Payable); + nodeFactory.markEndPosition(); + auto expressionType = nodeFactory.createNode( + ElementaryTypeNameToken(Token::Address, 160, 0), + boost::make_optional(StateMutability::Payable) + ); + expression = nodeFactory.createNode(expressionType); + expectToken(Token::LParen, false); + } else expression = parsePrimaryExpression(); @@ -1725,8 +1736,10 @@ ASTPointer Parser::parsePrimaryExpression() unsigned firstSize; unsigned secondSize; tie(firstSize, secondSize) = m_scanner->currentTokenInfo(); - ElementaryTypeNameToken elementaryExpression(m_scanner->currentToken(), firstSize, secondSize); - expression = nodeFactory.createNode(elementaryExpression); + auto expressionType = nodeFactory.createNode( + ElementaryTypeNameToken(m_scanner->currentToken(), firstSize, secondSize) + ); + expression = nodeFactory.createNode(expressionType); m_scanner->next(); } else @@ -1838,8 +1851,10 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath() unsigned firstNum; unsigned secondNum; tie(firstNum, secondNum) = m_scanner->currentTokenInfo(); - ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum); - iap.path.push_back(ASTNodeFactory(*this).createNode(elemToken)); + auto expressionType = ASTNodeFactory(*this).createNode( + ElementaryTypeNameToken(m_scanner->currentToken(), firstNum, secondNum) + ); + iap.path.push_back(ASTNodeFactory(*this).createNode(expressionType)); m_scanner->next(); } while (m_scanner->currentToken() == Token::LBrack) @@ -1872,7 +1887,7 @@ ASTPointer Parser::typeNameFromIndexAccessStructure(Parser::IndexAcces if (auto typeName = dynamic_cast(_iap.path.front().get())) { solAssert(_iap.path.size() == 1, ""); - type = nodeFactory.createNode(typeName->typeName()); + type = nodeFactory.createNode(typeName->type().typeName()); } else { diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json index 88ce272dc..834fb1cc9 100644 --- a/test/libsolidity/ASTJSON/address_payable.json +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -4,10 +4,10 @@ { "C" : [ - 37 + 39 ] }, - "id" : 38, + "id" : 40, "nodeType" : "SourceUnit", "nodes" : [ @@ -17,10 +17,10 @@ "contractKind" : "contract", "documentation" : null, "fullyImplemented" : true, - "id" : 37, + "id" : 39, "linearizedBaseContracts" : [ - 37 + 39 ], "name" : "C", "nodeType" : "ContractDefinition", @@ -32,7 +32,7 @@ "name" : "m", "nodeType" : "VariableDeclaration", "overrides" : null, - "scope" : 37, + "scope" : 39, "src" : "17:44:1", "stateVariable" : true, "storageLocation" : "default", @@ -83,7 +83,7 @@ { "body" : { - "id" : 35, + "id" : 37, "nodeType" : "Block", "src" : "134:122:1", "statements" : @@ -101,7 +101,7 @@ "name" : "a", "nodeType" : "VariableDeclaration", "overrides" : null, - "scope" : 35, + "scope" : 37, "src" : "144:17:1", "stateVariable" : false, "storageLocation" : "default", @@ -242,7 +242,7 @@ "name" : "c", "nodeType" : "VariableDeclaration", "overrides" : null, - "scope" : 35, + "scope" : 37, "src" : "197:9:1", "stateVariable" : false, "storageLocation" : "default", @@ -268,7 +268,7 @@ "visibility" : "internal" } ], - "id" : 26, + "id" : 27, "initialValue" : { "argumentTypes" : null, @@ -276,15 +276,15 @@ [ { "argumentTypes" : null, - "id" : 24, + "id" : 25, "name" : "this", "nodeType" : "Identifier", "overloadedDeclarations" : [], - "referencedDeclaration" : 66, + "referencedDeclaration" : 68, "src" : "217:4:1", "typeDescriptions" : { - "typeIdentifier" : "t_contract$_C_$37", + "typeIdentifier" : "t_contract$_C_$39", "typeString" : "contract C" } } @@ -294,11 +294,11 @@ "argumentTypes" : [ { - "typeIdentifier" : "t_contract$_C_$37", + "typeIdentifier" : "t_contract$_C_$39", "typeString" : "contract C" } ], - "id" : 23, + "id" : 24, "isConstant" : false, "isLValue" : false, "isPure" : true, @@ -312,7 +312,7 @@ }, "typeName" : "address" }, - "id" : 25, + "id" : 26, "isConstant" : false, "isLValue" : false, "isPure" : false, @@ -334,7 +334,7 @@ "expression" : { "argumentTypes" : null, - "id" : 33, + "id" : 35, "isConstant" : false, "isLValue" : false, "isPure" : false, @@ -345,7 +345,7 @@ "baseExpression" : { "argumentTypes" : null, - "id" : 27, + "id" : 28, "name" : "m", "nodeType" : "Identifier", "overloadedDeclarations" : [], @@ -357,11 +357,11 @@ "typeString" : "mapping(address => address payable)" } }, - "id" : 29, + "id" : 30, "indexExpression" : { "argumentTypes" : null, - "id" : 28, + "id" : 29, "name" : "c", "nodeType" : "Identifier", "overloadedDeclarations" : [], @@ -395,7 +395,7 @@ { "argumentTypes" : null, "hexValue" : "30", - "id" : 31, + "id" : 33, "isConstant" : false, "isLValue" : false, "isPure" : true, @@ -421,7 +421,7 @@ "typeString" : "int_const 0" } ], - "id" : 30, + "id" : 32, "isConstant" : false, "isLValue" : false, "isPure" : true, @@ -435,7 +435,7 @@ }, "typeName" : "address" }, - "id" : 32, + "id" : 34, "isConstant" : false, "isLValue" : false, "isPure" : true, @@ -457,14 +457,14 @@ "typeString" : "address payable" } }, - "id" : 34, + "id" : 36, "nodeType" : "ExpressionStatement", "src" : "232:17:1" } ] }, "documentation" : null, - "id" : 36, + "id" : 38, "implemented" : true, "kind" : "function", "modifiers" : [], @@ -483,7 +483,7 @@ "name" : "arg", "nodeType" : "VariableDeclaration", "overrides" : null, - "scope" : 36, + "scope" : 38, "src" : "78:19:1", "stateVariable" : false, "storageLocation" : "default", @@ -523,7 +523,7 @@ "name" : "r", "nodeType" : "VariableDeclaration", "overrides" : null, - "scope" : 36, + "scope" : 38, "src" : "115:17:1", "stateVariable" : false, "storageLocation" : "default", @@ -551,14 +551,14 @@ ], "src" : "114:19:1" }, - "scope" : 37, + "scope" : 39, "src" : "67:189:1", "stateMutability" : "nonpayable", "superFunction" : null, "visibility" : "public" } ], - "scope" : 38, + "scope" : 40, "src" : "0:258:1" } ], diff --git a/test/libsolidity/ASTJSON/address_payable_legacy.json b/test/libsolidity/ASTJSON/address_payable_legacy.json index a2758b16b..0b1072460 100644 --- a/test/libsolidity/ASTJSON/address_payable_legacy.json +++ b/test/libsolidity/ASTJSON/address_payable_legacy.json @@ -6,7 +6,7 @@ { "C" : [ - 37 + 39 ] } }, @@ -28,10 +28,10 @@ "fullyImplemented" : true, "linearizedBaseContracts" : [ - 37 + 39 ], "name" : "C", - "scope" : 38 + "scope" : 40 }, "children" : [ @@ -41,7 +41,7 @@ "constant" : false, "name" : "m", "overrides" : null, - "scope" : 37, + "scope" : 39, "stateVariable" : true, "storageLocation" : "default", "type" : "mapping(address => address payable)", @@ -101,7 +101,7 @@ ], "name" : "f", "overrides" : null, - "scope" : 37, + "scope" : 39, "stateMutability" : "nonpayable", "superFunction" : null, "visibility" : "public" @@ -117,7 +117,7 @@ "constant" : false, "name" : "arg", "overrides" : null, - "scope" : 36, + "scope" : 38, "stateVariable" : false, "storageLocation" : "default", "type" : "address payable", @@ -156,7 +156,7 @@ "constant" : false, "name" : "r", "overrides" : null, - "scope" : 36, + "scope" : 38, "stateVariable" : false, "storageLocation" : "default", "type" : "address payable", @@ -205,7 +205,7 @@ "constant" : false, "name" : "a", "overrides" : null, - "scope" : 35, + "scope" : 37, "stateVariable" : false, "storageLocation" : "default", "type" : "address payable", @@ -358,7 +358,7 @@ "constant" : false, "name" : "c", "overrides" : null, - "scope" : 35, + "scope" : 37, "stateVariable" : false, "storageLocation" : "default", "type" : "address", @@ -407,7 +407,7 @@ "argumentTypes" : [ { - "typeIdentifier" : "t_contract$_C_$37", + "typeIdentifier" : "t_contract$_C_$39", "typeString" : "contract C" } ], @@ -418,7 +418,7 @@ "type" : "type(address)", "value" : "address" }, - "id" : 23, + "id" : 24, "name" : "ElementaryTypeNameExpression", "src" : "209:7:1" }, @@ -430,21 +430,21 @@ [ null ], - "referencedDeclaration" : 66, + "referencedDeclaration" : 68, "type" : "contract C", "value" : "this" }, - "id" : 24, + "id" : 25, "name" : "Identifier", "src" : "217:4:1" } ], - "id" : 25, + "id" : 26, "name" : "FunctionCall", "src" : "209:13:1" } ], - "id" : 26, + "id" : 27, "name" : "VariableDeclarationStatement", "src" : "197:25:1" }, @@ -488,7 +488,7 @@ "type" : "mapping(address => address payable)", "value" : "m" }, - "id" : 27, + "id" : 28, "name" : "Identifier", "src" : "232:1:1" }, @@ -504,12 +504,12 @@ "type" : "address", "value" : "c" }, - "id" : 28, + "id" : 29, "name" : "Identifier", "src" : "234:1:1" } ], - "id" : 29, + "id" : 30, "name" : "IndexAccess", "src" : "232:4:1" }, @@ -548,7 +548,7 @@ "type" : "type(address)", "value" : "address" }, - "id" : 30, + "id" : 32, "name" : "ElementaryTypeNameExpression", "src" : "239:7:1" }, @@ -566,42 +566,42 @@ "type" : "int_const 0", "value" : "0" }, - "id" : 31, + "id" : 33, "name" : "Literal", "src" : "247:1:1" } ], - "id" : 32, + "id" : 34, "name" : "FunctionCall", "src" : "239:10:1" } ], - "id" : 33, + "id" : 35, "name" : "Assignment", "src" : "232:17:1" } ], - "id" : 34, + "id" : 36, "name" : "ExpressionStatement", "src" : "232:17:1" } ], - "id" : 35, + "id" : 37, "name" : "Block", "src" : "134:122:1" } ], - "id" : 36, + "id" : 38, "name" : "FunctionDefinition", "src" : "67:189:1" } ], - "id" : 37, + "id" : 39, "name" : "ContractDefinition", "src" : "0:258:1" } ], - "id" : 38, + "id" : 40, "name" : "SourceUnit", "src" : "0:259:1" } diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier.json b/test/libsolidity/ASTJSON/long_type_name_identifier.json index dc0c6447f..595f5b641 100644 --- a/test/libsolidity/ASTJSON/long_type_name_identifier.json +++ b/test/libsolidity/ASTJSON/long_type_name_identifier.json @@ -4,10 +4,10 @@ { "c" : [ - 14 + 15 ] }, - "id" : 15, + "id" : 16, "nodeType" : "SourceUnit", "nodes" : [ @@ -17,10 +17,10 @@ "contractKind" : "contract", "documentation" : null, "fullyImplemented" : true, - "id" : 14, + "id" : 15, "linearizedBaseContracts" : [ - 14 + 15 ], "name" : "c", "nodeType" : "ContractDefinition", @@ -32,7 +32,7 @@ "name" : "a", "nodeType" : "VariableDeclaration", "overrides" : null, - "scope" : 14, + "scope" : 15, "src" : "13:8:1", "stateVariable" : true, "storageLocation" : "default", @@ -71,7 +71,7 @@ { "body" : { - "id" : 12, + "id" : 13, "nodeType" : "Block", "src" : "43:25:1", "statements" : @@ -79,17 +79,17 @@ { "assignments" : [ - 9 + 10 ], "declarations" : [ { "constant" : false, - "id" : 9, + "id" : 10, "name" : "b", "nodeType" : "VariableDeclaration", "overrides" : null, - "scope" : 12, + "scope" : 13, "src" : "45:16:1", "stateVariable" : false, "storageLocation" : "storage", @@ -102,7 +102,7 @@ { "baseType" : { - "id" : 7, + "id" : 8, "name" : "uint", "nodeType" : "ElementaryTypeName", "src" : "45:4:1", @@ -112,7 +112,7 @@ "typeString" : "uint256" } }, - "id" : 8, + "id" : 9, "length" : null, "nodeType" : "ArrayTypeName", "src" : "45:6:1", @@ -126,11 +126,11 @@ "visibility" : "internal" } ], - "id" : 11, + "id" : 12, "initialValue" : { "argumentTypes" : null, - "id" : 10, + "id" : 11, "name" : "a", "nodeType" : "Identifier", "overloadedDeclarations" : [], @@ -148,7 +148,7 @@ ] }, "documentation" : null, - "id" : 13, + "id" : 14, "implemented" : true, "kind" : "function", "modifiers" : [], @@ -169,14 +169,14 @@ "parameters" : [], "src" : "43:0:1" }, - "scope" : 14, + "scope" : 15, "src" : "23:45:1", "stateMutability" : "nonpayable", "superFunction" : null, "visibility" : "public" } ], - "scope" : 15, + "scope" : 16, "src" : "0:70:1" } ], diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json b/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json index 457677089..1f222fe84 100644 --- a/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json +++ b/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json @@ -6,7 +6,7 @@ { "c" : [ - 14 + 15 ] } }, @@ -28,10 +28,10 @@ "fullyImplemented" : true, "linearizedBaseContracts" : [ - 14 + 15 ], "name" : "c", - "scope" : 15 + "scope" : 16 }, "children" : [ @@ -41,7 +41,7 @@ "constant" : false, "name" : "a", "overrides" : null, - "scope" : 14, + "scope" : 15, "stateVariable" : true, "storageLocation" : "default", "type" : "uint256[]", @@ -91,7 +91,7 @@ ], "name" : "f", "overrides" : null, - "scope" : 14, + "scope" : 15, "stateMutability" : "nonpayable", "superFunction" : null, "visibility" : "public" @@ -132,7 +132,7 @@ { "assignments" : [ - 9 + 10 ] }, "children" : @@ -143,7 +143,7 @@ "constant" : false, "name" : "b", "overrides" : null, - "scope" : 12, + "scope" : 13, "stateVariable" : false, "storageLocation" : "storage", "type" : "uint256[]", @@ -166,17 +166,17 @@ "name" : "uint", "type" : "uint256" }, - "id" : 7, + "id" : 8, "name" : "ElementaryTypeName", "src" : "45:4:1" } ], - "id" : 8, + "id" : 9, "name" : "ArrayTypeName", "src" : "45:6:1" } ], - "id" : 9, + "id" : 10, "name" : "VariableDeclaration", "src" : "45:16:1" }, @@ -192,32 +192,32 @@ "type" : "uint256[] storage ref", "value" : "a" }, - "id" : 10, + "id" : 11, "name" : "Identifier", "src" : "64:1:1" } ], - "id" : 11, + "id" : 12, "name" : "VariableDeclarationStatement", "src" : "45:20:1" } ], - "id" : 12, + "id" : 13, "name" : "Block", "src" : "43:25:1" } ], - "id" : 13, + "id" : 14, "name" : "FunctionDefinition", "src" : "23:45:1" } ], - "id" : 14, + "id" : 15, "name" : "ContractDefinition", "src" : "0:70:1" } ], - "id" : 15, + "id" : 16, "name" : "SourceUnit", "src" : "0:71:1" } diff --git a/test/libsolidity/ASTJSON/short_type_name.json b/test/libsolidity/ASTJSON/short_type_name.json index 823d04d3d..d599be955 100644 --- a/test/libsolidity/ASTJSON/short_type_name.json +++ b/test/libsolidity/ASTJSON/short_type_name.json @@ -4,10 +4,10 @@ { "c" : [ - 10 + 11 ] }, - "id" : 11, + "id" : 12, "nodeType" : "SourceUnit", "nodes" : [ @@ -17,10 +17,10 @@ "contractKind" : "contract", "documentation" : null, "fullyImplemented" : true, - "id" : 10, + "id" : 11, "linearizedBaseContracts" : [ - 10 + 11 ], "name" : "c", "nodeType" : "ContractDefinition", @@ -29,7 +29,7 @@ { "body" : { - "id" : 8, + "id" : 9, "nodeType" : "Block", "src" : "33:20:1", "statements" : @@ -37,17 +37,17 @@ { "assignments" : [ - 6 + 7 ], "declarations" : [ { "constant" : false, - "id" : 6, + "id" : 7, "name" : "x", "nodeType" : "VariableDeclaration", "overrides" : null, - "scope" : 8, + "scope" : 9, "src" : "35:15:1", "stateVariable" : false, "storageLocation" : "memory", @@ -60,7 +60,7 @@ { "baseType" : { - "id" : 4, + "id" : 5, "name" : "uint", "nodeType" : "ElementaryTypeName", "src" : "35:4:1", @@ -70,7 +70,7 @@ "typeString" : "uint256" } }, - "id" : 5, + "id" : 6, "length" : null, "nodeType" : "ArrayTypeName", "src" : "35:6:1", @@ -84,7 +84,7 @@ "visibility" : "internal" } ], - "id" : 7, + "id" : 8, "initialValue" : null, "nodeType" : "VariableDeclarationStatement", "src" : "35:15:1" @@ -92,7 +92,7 @@ ] }, "documentation" : null, - "id" : 9, + "id" : 10, "implemented" : true, "kind" : "function", "modifiers" : [], @@ -113,14 +113,14 @@ "parameters" : [], "src" : "33:0:1" }, - "scope" : 10, + "scope" : 11, "src" : "13:40:1", "stateMutability" : "nonpayable", "superFunction" : null, "visibility" : "public" } ], - "scope" : 11, + "scope" : 12, "src" : "0:55:1" } ], diff --git a/test/libsolidity/ASTJSON/short_type_name_legacy.json b/test/libsolidity/ASTJSON/short_type_name_legacy.json index ee4d1fce3..92d0abc30 100644 --- a/test/libsolidity/ASTJSON/short_type_name_legacy.json +++ b/test/libsolidity/ASTJSON/short_type_name_legacy.json @@ -6,7 +6,7 @@ { "c" : [ - 10 + 11 ] } }, @@ -28,10 +28,10 @@ "fullyImplemented" : true, "linearizedBaseContracts" : [ - 10 + 11 ], "name" : "c", - "scope" : 11 + "scope" : 12 }, "children" : [ @@ -48,7 +48,7 @@ ], "name" : "f", "overrides" : null, - "scope" : 10, + "scope" : 11, "stateMutability" : "nonpayable", "superFunction" : null, "visibility" : "public" @@ -89,7 +89,7 @@ { "assignments" : [ - 6 + 7 ], "initialValue" : null }, @@ -101,7 +101,7 @@ "constant" : false, "name" : "x", "overrides" : null, - "scope" : 8, + "scope" : 9, "stateVariable" : false, "storageLocation" : "memory", "type" : "uint256[]", @@ -124,42 +124,42 @@ "name" : "uint", "type" : "uint256" }, - "id" : 4, + "id" : 5, "name" : "ElementaryTypeName", "src" : "35:4:1" } ], - "id" : 5, + "id" : 6, "name" : "ArrayTypeName", "src" : "35:6:1" } ], - "id" : 6, + "id" : 7, "name" : "VariableDeclaration", "src" : "35:15:1" } ], - "id" : 7, + "id" : 8, "name" : "VariableDeclarationStatement", "src" : "35:15:1" } ], - "id" : 8, + "id" : 9, "name" : "Block", "src" : "33:20:1" } ], - "id" : 9, + "id" : 10, "name" : "FunctionDefinition", "src" : "13:40:1" } ], - "id" : 10, + "id" : 11, "name" : "ContractDefinition", "src" : "0:55:1" } ], - "id" : 11, + "id" : 12, "name" : "SourceUnit", "src" : "0:56:1" } diff --git a/test/libsolidity/ASTJSON/short_type_name_ref.json b/test/libsolidity/ASTJSON/short_type_name_ref.json index 5224f26f2..51a13102f 100644 --- a/test/libsolidity/ASTJSON/short_type_name_ref.json +++ b/test/libsolidity/ASTJSON/short_type_name_ref.json @@ -4,10 +4,10 @@ { "c" : [ - 11 + 12 ] }, - "id" : 12, + "id" : 13, "nodeType" : "SourceUnit", "nodes" : [ @@ -17,10 +17,10 @@ "contractKind" : "contract", "documentation" : null, "fullyImplemented" : true, - "id" : 11, + "id" : 12, "linearizedBaseContracts" : [ - 11 + 12 ], "name" : "c", "nodeType" : "ContractDefinition", @@ -29,7 +29,7 @@ { "body" : { - "id" : 9, + "id" : 10, "nodeType" : "Block", "src" : "33:25:1", "statements" : @@ -37,17 +37,17 @@ { "assignments" : [ - 7 + 8 ], "declarations" : [ { "constant" : false, - "id" : 7, + "id" : 8, "name" : "rows", "nodeType" : "VariableDeclaration", "overrides" : null, - "scope" : 9, + "scope" : 10, "src" : "35:20:1", "stateVariable" : false, "storageLocation" : "memory", @@ -62,7 +62,7 @@ { "baseType" : { - "id" : 4, + "id" : 5, "name" : "uint", "nodeType" : "ElementaryTypeName", "src" : "35:4:1", @@ -72,7 +72,7 @@ "typeString" : "uint256" } }, - "id" : 5, + "id" : 6, "length" : null, "nodeType" : "ArrayTypeName", "src" : "35:6:1", @@ -82,7 +82,7 @@ "typeString" : "uint256[]" } }, - "id" : 6, + "id" : 7, "length" : null, "nodeType" : "ArrayTypeName", "src" : "35:8:1", @@ -96,7 +96,7 @@ "visibility" : "internal" } ], - "id" : 8, + "id" : 9, "initialValue" : null, "nodeType" : "VariableDeclarationStatement", "src" : "35:20:1" @@ -104,7 +104,7 @@ ] }, "documentation" : null, - "id" : 10, + "id" : 11, "implemented" : true, "kind" : "function", "modifiers" : [], @@ -125,14 +125,14 @@ "parameters" : [], "src" : "33:0:1" }, - "scope" : 11, + "scope" : 12, "src" : "13:45:1", "stateMutability" : "nonpayable", "superFunction" : null, "visibility" : "public" } ], - "scope" : 12, + "scope" : 13, "src" : "0:60:1" } ], diff --git a/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json b/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json index 0fbecedf8..99b4d550e 100644 --- a/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json +++ b/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json @@ -6,7 +6,7 @@ { "c" : [ - 11 + 12 ] } }, @@ -28,10 +28,10 @@ "fullyImplemented" : true, "linearizedBaseContracts" : [ - 11 + 12 ], "name" : "c", - "scope" : 12 + "scope" : 13 }, "children" : [ @@ -48,7 +48,7 @@ ], "name" : "f", "overrides" : null, - "scope" : 11, + "scope" : 12, "stateMutability" : "nonpayable", "superFunction" : null, "visibility" : "public" @@ -89,7 +89,7 @@ { "assignments" : [ - 7 + 8 ], "initialValue" : null }, @@ -101,7 +101,7 @@ "constant" : false, "name" : "rows", "overrides" : null, - "scope" : 9, + "scope" : 10, "stateVariable" : false, "storageLocation" : "memory", "type" : "uint256[][]", @@ -132,47 +132,47 @@ "name" : "uint", "type" : "uint256" }, - "id" : 4, + "id" : 5, "name" : "ElementaryTypeName", "src" : "35:4:1" } ], - "id" : 5, + "id" : 6, "name" : "ArrayTypeName", "src" : "35:6:1" } ], - "id" : 6, + "id" : 7, "name" : "ArrayTypeName", "src" : "35:8:1" } ], - "id" : 7, + "id" : 8, "name" : "VariableDeclaration", "src" : "35:20:1" } ], - "id" : 8, + "id" : 9, "name" : "VariableDeclarationStatement", "src" : "35:20:1" } ], - "id" : 9, + "id" : 10, "name" : "Block", "src" : "33:25:1" } ], - "id" : 10, + "id" : 11, "name" : "FunctionDefinition", "src" : "13:45:1" } ], - "id" : 11, + "id" : 12, "name" : "ContractDefinition", "src" : "0:60:1" } ], - "id" : 12, + "id" : 13, "name" : "SourceUnit", "src" : "0:61:1" } diff --git a/test/libsolidity/syntaxTests/conversion/explicit_conversion_address_to_payable.sol b/test/libsolidity/syntaxTests/conversion/explicit_conversion_address_to_payable.sol new file mode 100644 index 000000000..d44841fd7 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/explicit_conversion_address_to_payable.sol @@ -0,0 +1,11 @@ +contract C { + function g(address payable _p) internal pure returns (uint) { + return 1; + } + function f(address _a) public pure { + uint x = g(payable(_a)); + uint y = g(_a); + } +} +// ---- +// TypeError: (169-171): Invalid type for argument in function call. Invalid implicit conversion from address to address payable requested. diff --git a/test/libsolidity/syntaxTests/conversion/explicit_conversion_sender_to_payable.sol b/test/libsolidity/syntaxTests/conversion/explicit_conversion_sender_to_payable.sol new file mode 100644 index 000000000..141a12546 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/explicit_conversion_sender_to_payable.sol @@ -0,0 +1,9 @@ +contract C { + function f() public view { + address payable p = payable(msg.sender); + address payable q = payable(address(msg.sender)); + } +} +// ---- +// Warning: (43-60): Unused local variable. +// Warning: (86-103): Unused local variable. diff --git a/test/libsolidity/syntaxTests/conversion/explicit_conversion_this_to_payable.sol b/test/libsolidity/syntaxTests/conversion/explicit_conversion_this_to_payable.sol new file mode 100644 index 000000000..7f5519cdf --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/explicit_conversion_this_to_payable.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure { + address payable p = payable(this); + address payable q = payable(address(this)); + } +} +// ---- +// TypeError: (63-76): Explicit type conversion not allowed from "contract C" to "address payable". diff --git a/test/libsolidity/syntaxTests/parsing/payable_without_arguments.sol b/test/libsolidity/syntaxTests/parsing/payable_without_arguments.sol new file mode 100644 index 000000000..b9486f596 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/payable_without_arguments.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + address payable q = payable; + } +} +// ---- +// ParserError: (70-71): Expected '(' but got ';'