mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Allow exponentials with signed base and unsigned power.
This commit is contained in:
parent
c499758cd8
commit
33f7f960cf
@ -2,6 +2,7 @@
|
||||
|
||||
Breaking changes:
|
||||
* General: Disallow explicit conversions from external function types to ``address`` and add a member called ``address`` to them as replacement.
|
||||
* Type checker: Resulting type of exponentiation is equal to the type of the base. Also allow signed types for the base.
|
||||
|
||||
|
||||
Language Features:
|
||||
|
@ -29,6 +29,10 @@ Semantic and Syntactic Changes
|
||||
|
||||
This section highlights changes that affect syntax and semantics.
|
||||
|
||||
* The resulting type of an exponentiation is the type of the base. It used to be the smallest type
|
||||
that can hold both the type of the base and the type of the exponent, as with symmentric
|
||||
operations. Additionally, signed types are allowed for the base of the exponetation.
|
||||
|
||||
|
||||
How to update your code
|
||||
=======================
|
||||
|
@ -123,8 +123,9 @@ results in the same sign as its left operand (or zero) and ``a % n == -(abs(a) %
|
||||
Exponentiation
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Exponentiation is only available for unsigned types. Please take care that the types
|
||||
you are using are large enough to hold the result and prepare for potential wrapping behaviour.
|
||||
Exponentiation is only available for unsigned types in the exponent. The resulting type
|
||||
of an exponentiation is always equal to the type of the base. Please take care that it is
|
||||
large enough to hold the result and prepare for potential wrapping behaviour.
|
||||
|
||||
.. note::
|
||||
Note that ``0**0`` is defined by the EVM as ``1``.
|
||||
|
@ -1397,6 +1397,23 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
||||
"might overflow. Silence this warning by converting the literal to the "
|
||||
"expected type."
|
||||
);
|
||||
if (
|
||||
commonType->category() == Type::Category::Integer &&
|
||||
rightType->category() == Type::Category::Integer &&
|
||||
dynamic_cast<IntegerType const&>(*commonType).numBits() <
|
||||
dynamic_cast<IntegerType const&>(*rightType).numBits()
|
||||
)
|
||||
m_errorReporter.warning(
|
||||
_operation.location(),
|
||||
"The result type of the " +
|
||||
operation +
|
||||
" operation is equal to the type of the first operand (" +
|
||||
commonType->toString() +
|
||||
") ignoring the (larger) type of the second operand (" +
|
||||
rightType->toString() +
|
||||
") which might be unexpected. Silence this warning by either converting "
|
||||
"the first or the second operand to the type of the other."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,6 +600,17 @@ TypeResult IntegerType::binaryOperatorResult(Token _operator, Type const* _other
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
else if (Token::Exp == _operator)
|
||||
{
|
||||
if (auto otherIntType = dynamic_cast<IntegerType const*>(_other))
|
||||
{
|
||||
if (otherIntType->isSigned())
|
||||
return TypeResult::err("Exponentiation power is not allowed to be a signed integer type.");
|
||||
}
|
||||
else if (dynamic_cast<FixedPointType const*>(_other))
|
||||
return nullptr;
|
||||
return this;
|
||||
}
|
||||
|
||||
auto commonType = Type::commonType(this, _other); //might be an integer or fixed point
|
||||
if (!commonType)
|
||||
@ -610,14 +621,6 @@ TypeResult IntegerType::binaryOperatorResult(Token _operator, Type const* _other
|
||||
return commonType;
|
||||
if (TokenTraits::isBooleanOp(_operator))
|
||||
return nullptr;
|
||||
if (auto intType = dynamic_cast<IntegerType const*>(commonType))
|
||||
{
|
||||
if (Token::Exp == _operator && intType->isSigned())
|
||||
return TypeResult::err("Exponentiation is not allowed for signed integer types.");
|
||||
}
|
||||
else if (dynamic_cast<FixedPointType const*>(commonType))
|
||||
if (Token::Exp == _operator)
|
||||
return nullptr;
|
||||
return commonType;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
contract test {
|
||||
function f() public pure returns (int, int) {
|
||||
int32 x = -3;
|
||||
uint8 y1;
|
||||
uint8 y2;
|
||||
assembly {
|
||||
y1 := 0x102
|
||||
y2 := 0x103
|
||||
}
|
||||
return (x**y1, x**y2);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f() -> 9, -27
|
13
test/libsolidity/semanticTests/exponentiation/small_exp.sol
Normal file
13
test/libsolidity/semanticTests/exponentiation/small_exp.sol
Normal file
@ -0,0 +1,13 @@
|
||||
contract test {
|
||||
function f() public pure returns (uint) {
|
||||
uint32 x;
|
||||
uint8 y;
|
||||
assembly {
|
||||
x := 0xfffffffffe
|
||||
y := 0x102
|
||||
}
|
||||
return x**y;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f() -> 4
|
@ -1,3 +1,3 @@
|
||||
contract test { function() external { uint x = 3; int y = -4; x ** y; } }
|
||||
// ----
|
||||
// TypeError: (62-68): Operator ** not compatible with types uint256 and int256
|
||||
// TypeError: (62-68): Operator ** not compatible with types uint256 and int256. Exponentiation power is not allowed to be a signed integer type.
|
||||
|
@ -1,3 +1,5 @@
|
||||
contract test { function() external { uint x = 3; int y = -4; y ** x; } }
|
||||
// ----
|
||||
// TypeError: (62-68): Operator ** not compatible with types int256 and uint256
|
||||
contract test {
|
||||
function() external { uint x = 3; int y = -4; y ** x; }
|
||||
function f() public pure { int16 x = 3; uint8 y = 4; x ** y; }
|
||||
function g() public pure { int16 x = 3; uint16 y = 4; x ** y; }
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
contract test {
|
||||
function f() public { int x = 3; int y = 4; x ** y; }
|
||||
function g() public { int16 x = 3; uint8 y = 4; x ** y; }
|
||||
function h() public { uint8 x = 3; int16 y = 4; x ** y; }
|
||||
}
|
||||
// ----
|
||||
// TypeError: (64-70): Operator ** not compatible with types int256 and int256. Exponentiation is not allowed for signed integer types.
|
||||
// TypeError: (126-132): Operator ** not compatible with types int16 and uint8. Exponentiation is not allowed for signed integer types.
|
||||
// TypeError: (188-194): Operator ** not compatible with types uint8 and int16. Exponentiation is not allowed for signed integer types.
|
||||
// TypeError: (64-70): Operator ** not compatible with types int256 and int256. Exponentiation power is not allowed to be a signed integer type.
|
||||
// TypeError: (126-132): Operator ** not compatible with types uint8 and int16. Exponentiation power is not allowed to be a signed integer type.
|
||||
// Warning: (126-132): The result type of the exponentiation operation is equal to the type of the first operand (uint8) ignoring the (larger) type of the second operand (int16) which might be unexpected. Silence this warning by either converting the first or the second operand to the type of the other.
|
||||
|
Loading…
Reference in New Issue
Block a user