mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Disallow specifying call options multiple times.
This commit is contained in:
parent
ce50f05fc1
commit
b287a6e995
@ -4,6 +4,7 @@ Breaking Changes:
|
|||||||
* Assembler: The artificial ASSIGNIMMUTABLE opcode and the corresponding builtin in the "EVM with object access" dialect of Yul take the base offset of the code to modify as additional argument.
|
* Assembler: The artificial ASSIGNIMMUTABLE opcode and the corresponding builtin in the "EVM with object access" dialect of Yul take the base offset of the code to modify as additional argument.
|
||||||
* Code Generator: All arithmetic is checked by default. These checks can be disabled using ``unchecked { ... }``.
|
* Code Generator: All arithmetic is checked by default. These checks can be disabled using ``unchecked { ... }``.
|
||||||
* General: Remove global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4``.
|
* General: Remove global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4``.
|
||||||
|
* Type Checker: Function call options can only be given once.
|
||||||
* Type System: Unary negation can only be used on signed integers, not on unsigned integers.
|
* Type System: Unary negation can only be used on signed integers, not on unsigned integers.
|
||||||
* Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type.
|
* Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type.
|
||||||
* Parser: Exponentiation is right associative. ``a**b**c`` is parsed as ``a**(b**c)``.
|
* Parser: Exponentiation is right associative. ``a**b**c`` is parsed as ``a**(b**c)``.
|
||||||
|
@ -40,6 +40,8 @@ New Restrictions
|
|||||||
|
|
||||||
The previous behaviour was likely ambiguous.
|
The previous behaviour was likely ambiguous.
|
||||||
|
|
||||||
|
* Function call options can only be given once, i.e. ``c.f{gas: 10000}{value: 1}()`` is invalid and has to be changed to ``c.f{gas: 10000, value: 1}()``.
|
||||||
|
|
||||||
* The global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4`` have been removed.
|
* The global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4`` have been removed.
|
||||||
|
|
||||||
These are low-level functions that were largely unused. Their behaviour can be accessed from inline assembly.
|
These are low-level functions that were largely unused. Their behaviour can be accessed from inline assembly.
|
@ -2425,14 +2425,24 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto setCheckOption = [&](bool& _option, string const&& _name, bool _alreadySet = false)
|
if (
|
||||||
|
expressionFunctionType->valueSet() ||
|
||||||
|
expressionFunctionType->gasSet() ||
|
||||||
|
expressionFunctionType->saltSet()
|
||||||
|
)
|
||||||
|
m_errorReporter.typeError(
|
||||||
|
1645_error,
|
||||||
|
_functionCallOptions.location(),
|
||||||
|
"Function call options have already been set, you have to combine them into a single "
|
||||||
|
"{...}-option."
|
||||||
|
);
|
||||||
|
|
||||||
|
auto setCheckOption = [&](bool& _option, string const& _name)
|
||||||
{
|
{
|
||||||
if (_option || _alreadySet)
|
if (_option)
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
9886_error,
|
9886_error,
|
||||||
_functionCallOptions.location(),
|
_functionCallOptions.location(),
|
||||||
_alreadySet ?
|
|
||||||
"Option \"" + std::move(_name) + "\" has already been set." :
|
|
||||||
"Duplicate option \"" + std::move(_name) + "\"."
|
"Duplicate option \"" + std::move(_name) + "\"."
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2446,7 +2456,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
|
|||||||
{
|
{
|
||||||
if (kind == FunctionType::Kind::Creation)
|
if (kind == FunctionType::Kind::Creation)
|
||||||
{
|
{
|
||||||
setCheckOption(setSalt, "salt", expressionFunctionType->saltSet());
|
setCheckOption(setSalt, "salt");
|
||||||
expectType(*_functionCallOptions.options()[i], *TypeProvider::fixedBytes(32));
|
expectType(*_functionCallOptions.options()[i], *TypeProvider::fixedBytes(32));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2484,7 +2494,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
|
|||||||
{
|
{
|
||||||
expectType(*_functionCallOptions.options()[i], *TypeProvider::uint256());
|
expectType(*_functionCallOptions.options()[i], *TypeProvider::uint256());
|
||||||
|
|
||||||
setCheckOption(setValue, "value", expressionFunctionType->valueSet());
|
setCheckOption(setValue, "value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (name == "gas")
|
else if (name == "gas")
|
||||||
@ -2499,7 +2509,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
|
|||||||
{
|
{
|
||||||
expectType(*_functionCallOptions.options()[i], *TypeProvider::uint256());
|
expectType(*_functionCallOptions.options()[i], *TypeProvider::uint256());
|
||||||
|
|
||||||
setCheckOption(setGas, "gas", expressionFunctionType->gasSet());
|
setCheckOption(setGas, "gas");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -5,8 +5,9 @@ contract C {
|
|||||||
v = this.f{value: 10}(2);
|
v = this.f{value: 10}(2);
|
||||||
x = this.f{gas: 1000}(2, 3);
|
x = this.f{gas: 1000}(2, 3);
|
||||||
y = this.f{gas: 1000, value: 10}(2, 3);
|
y = this.f{gas: 1000, value: 10}(2, 3);
|
||||||
z = this.f{gas: 1000}{value: 10}(2, 3);
|
z = this.f{value: 10, gas: 1000}(2, 3);
|
||||||
}
|
}
|
||||||
|
function bal() external returns (uint) { return address(this).balance; }
|
||||||
receive() external payable {}
|
receive() external payable {}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
@ -14,3 +15,4 @@ contract C {
|
|||||||
// ----
|
// ----
|
||||||
// (), 1 ether
|
// (), 1 ether
|
||||||
// call() -> 1, 2, 2, 2
|
// call() -> 1, 2, 2, 2
|
||||||
|
// bal() -> 1000000000000000000
|
||||||
|
@ -12,8 +12,8 @@ contract B
|
|||||||
contract A {
|
contract A {
|
||||||
function f() public payable returns (uint, uint, uint) {
|
function f() public payable returns (uint, uint, uint) {
|
||||||
B x = new B{salt: "abc", value: 3}(7);
|
B x = new B{salt: "abc", value: 3}(7);
|
||||||
B y = new B{value: 3}{salt: "abc"}(8);
|
B y = new B{value: 3, salt: "abc"}(8);
|
||||||
B z = new B{value: 3, salt: "abc"}(9);
|
B z = new B{salt: "abc", value: 3}(9);
|
||||||
return (x.getBalance(), y.getBalance(), z.getBalance());
|
return (x.getBalance(), y.getBalance(), z.getBalance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,8 @@ contract C {
|
|||||||
// ====
|
// ====
|
||||||
// EVMVersion: >=constantinople
|
// EVMVersion: >=constantinople
|
||||||
// ----
|
// ----
|
||||||
// TypeError 9886: (78-110): Option "gas" has already been set.
|
// TypeError 1645: (78-110): Function call options have already been set, you have to combine them into a single {...}-option.
|
||||||
// TypeError 9886: (120-154): Option "gas" has already been set.
|
// TypeError 1645: (120-154): Function call options have already been set, you have to combine them into a single {...}-option.
|
||||||
// TypeError 9886: (164-198): Option "value" has already been set.
|
// TypeError 1645: (164-198): Function call options have already been set, you have to combine them into a single {...}-option.
|
||||||
// TypeError 9886: (208-249): Option "value" has already been set.
|
// TypeError 1645: (208-249): Function call options have already been set, you have to combine them into a single {...}-option.
|
||||||
// TypeError 9886: (208-249): Option "gas" has already been set.
|
// TypeError 1645: (259-286): Function call options have already been set, you have to combine them into a single {...}-option.
|
||||||
// TypeError 9886: (259-286): Option "salt" has already been set.
|
|
||||||
|
Loading…
Reference in New Issue
Block a user