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 ';'