Merge pull request #9494 from ethereum/fixExp07

Fix conversion bug for exp operation.
This commit is contained in:
chriseth 2020-07-27 10:45:14 +02:00 committed by GitHub
commit 82e5e80cba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 4 deletions

View File

@ -286,6 +286,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
m_currentLValue->storeValue(*rightIntermediateType, _assignment.location());
else // compound assignment
{
solAssert(binOp != Token::Exp, "Compound exp is not possible.");
solAssert(leftType.isValueType(), "Compound operators only available for value types.");
unsigned lvalueSize = m_currentLValue->sizeOnStack();
unsigned itemSize = _assignment.annotation().type->sizeOnStack();
@ -452,7 +453,10 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
bool cleanupNeeded = cleanupNeededForOp(commonType->category(), c_op);
TypePointer leftTargetType = commonType;
TypePointer rightTargetType = TokenTraits::isShiftOp(c_op) ? rightExpression.annotation().type->mobileType() : commonType;
TypePointer rightTargetType =
TokenTraits::isShiftOp(c_op) || c_op == Token::Exp ?
rightExpression.annotation().type->mobileType() :
commonType;
solAssert(rightTargetType, "");
// for commutative operators, push the literal as late as possible to allow improved optimization
@ -474,6 +478,8 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
if (TokenTraits::isShiftOp(c_op))
// shift only cares about the signedness of both sides
appendShiftOperatorCode(c_op, *leftTargetType, *rightTargetType);
else if (c_op == Token::Exp)
appendExpOperatorCode(*leftTargetType, *rightTargetType);
else if (TokenTraits::isCompareOp(c_op))
appendCompareOperatorCode(c_op, *commonType);
else
@ -2080,9 +2086,6 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token _operator, Type cons
m_context << (c_isSigned ? Instruction::SMOD : Instruction::MOD);
break;
}
case Token::Exp:
m_context << Instruction::EXP;
break;
default:
solAssert(false, "Unknown arithmetic operator.");
}
@ -2177,6 +2180,14 @@ void ExpressionCompiler::appendShiftOperatorCode(Token _operator, Type const& _v
}
}
void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type const& _exponentType)
{
solAssert(_valueType.category() == Type::Category::Integer, "");
solAssert(!dynamic_cast<IntegerType const&>(_exponentType).isSigned(), "");
m_context << Instruction::EXP;
}
void ExpressionCompiler::appendExternalFunctionCall(
FunctionType const& _functionType,
vector<ASTPointer<Expression const>> const& _arguments,

View File

@ -101,6 +101,7 @@ private:
void appendArithmeticOperatorCode(Token _operator, Type const& _type);
void appendBitOperatorCode(Token _operator);
void appendShiftOperatorCode(Token _operator, Type const& _valueType, Type const& _shiftAmountType);
void appendExpOperatorCode(Type const& _valueType, Type const& _exponentType);
/// @}
/// Appends code to call a function of the given type with the given arguments.

View File

@ -0,0 +1,11 @@
contract C {
function f() public pure returns (uint16 x) {
// tests that ``e`` is not converted to uint8
// right before the exp
uint16 e = 0x100;
uint8 b = 0x2;
return b**e;
}
}
// ----
// f() -> 0x00