diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 22adb6a0f..4cf00c2cb 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -693,10 +693,16 @@ void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation) else solUnimplementedAssert(false, "Unary operator not yet implemented"); } + else if (resultType.category() == Type::Category::FixedBytes) + { + solAssert(op == Token::BitNot, "Only bitwise negation is allowed for FixedBytes"); + solAssert(resultType == type(_unaryOperation.subExpression()), "Result type doesn't match!"); + appendSimpleUnaryOperation(_unaryOperation, _unaryOperation.subExpression()); + } else if (resultType.category() == Type::Category::Bool) { solAssert( - _unaryOperation.getOperator() != Token::BitNot, + op != Token::BitNot, "Bitwise Negation can't be done on bool!" ); diff --git a/test/libsolidity/semanticTests/various/iszero_bnot_correct.sol b/test/libsolidity/semanticTests/various/iszero_bnot_correct.sol index 743825d60..e957fbc8e 100644 --- a/test/libsolidity/semanticTests/various/iszero_bnot_correct.sol +++ b/test/libsolidity/semanticTests/various/iszero_bnot_correct.sol @@ -15,5 +15,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f() -> true diff --git a/test/libsolidity/semanticTests/viaYul/unary_fixedbytes.sol b/test/libsolidity/semanticTests/viaYul/unary_fixedbytes.sol new file mode 100644 index 000000000..3f4d586e6 --- /dev/null +++ b/test/libsolidity/semanticTests/viaYul/unary_fixedbytes.sol @@ -0,0 +1,87 @@ +contract C { + function conv(bytes25 a) public pure returns (bytes32) { + // truncating and widening + return ~bytes32(bytes16(~a)); + } + + function upcast(bytes25 a) public pure returns (bytes32) { + // implicit widening is allowed + return ~a; + } + + function downcast(bytes25 a) public pure returns (bytes12) { + // truncating cast must be explicit + return bytes12(~a); + } + + function r_b32() public pure returns (bytes32) { + return ~bytes32(hex"ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00"); + } + function r_b25() public pure returns (bytes25) { + return ~bytes25(hex"ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff"); + } + function r_b16() public pure returns (bytes16) { + return ~bytes16(hex"ff00ff00ff00ff00ff00ff00ff00ff00"); + } + function r_b8() public pure returns (bytes8) { + return ~bytes8(hex"ff00ff00ff00ff00"); + } + function r_b4() public pure returns (bytes4) { + return ~bytes4(hex"ff00ff00"); + } + function r_b1() public pure returns (bytes1) { + return ~bytes1(hex"55"); + } + function r_b() public pure returns (byte) { + return ~byte(hex"55"); + } + + function a_b32() public pure returns (bytes32) { + bytes32 r = ~bytes32(hex"ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00"); + return r; + } + function a_b25() public pure returns (bytes25) { + bytes25 r = ~bytes25(hex"ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff"); + return r; + } + function a_b16() public pure returns (bytes16) { + bytes16 r = ~bytes16(hex"ff00ff00ff00ff00ff00ff00ff00ff00"); + return r; + } + function a_b8() public pure returns (bytes8) { + bytes8 r = ~bytes8(hex"ff00ff00ff00ff00"); + return r; + } + function a_b4() public pure returns (bytes4) { + bytes4 r = ~bytes4(hex"ff00ff00"); + return r; + } + function a_b1() public pure returns (byte) { + bytes1 r = ~bytes1(hex"55"); + return r; + } + function a_b() public pure returns (byte) { + byte r = ~byte(hex"55"); + return r; + } +} +// ==== +// compileViaYul: also +// ---- +// conv(bytes25): left(0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff) -> 0xff00ff00ff00ff00ff00ff00ff00ff00ffffffffffffffffffffffffffffffff +// upcast(bytes25): left(0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff) -> 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff0000000000000000 +// downcast(bytes25): left(0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff) -> 0xff00ff00ff00ff00ff00ff0000000000000000000000000000000000000000 +// r_b32() -> 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff +// r_b25() -> 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff0000000000000000 +// r_b16() -> 0xff00ff00ff00ff00ff00ff00ff00ff00000000000000000000000000000000 +// r_b8() -> 0xff00ff00ff00ff000000000000000000000000000000000000000000000000 +// r_b4() -> 0xff00ff00000000000000000000000000000000000000000000000000000000 +// r_b1() -> 0xaa00000000000000000000000000000000000000000000000000000000000000 +// r_b() -> 0xaa00000000000000000000000000000000000000000000000000000000000000 +// a_b32() -> 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff +// a_b25() -> 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff0000000000000000 +// a_b16() -> 0xff00ff00ff00ff00ff00ff00ff00ff00000000000000000000000000000000 +// a_b8() -> 0xff00ff00ff00ff000000000000000000000000000000000000000000000000 +// a_b4() -> 0xff00ff00000000000000000000000000000000000000000000000000000000 +// a_b1() -> 0xaa00000000000000000000000000000000000000000000000000000000000000 +// a_b() -> 0xaa00000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/syntaxTests/types/bytesNN_bitnot.sol b/test/libsolidity/syntaxTests/types/bytesNN_bitnot.sol new file mode 100644 index 000000000..b926beeb1 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytesNN_bitnot.sol @@ -0,0 +1,5 @@ +contract C { + bytes32 b32 = ~bytes32(hex"ff"); + bytes32 b25 = ~bytes25(hex"ff"); + bytes25 b8 = ~bytes8(hex"ff"); +} diff --git a/test/libsolidity/syntaxTests/types/hex_literal_bitnot.sol b/test/libsolidity/syntaxTests/types/hex_literal_bitnot.sol new file mode 100644 index 000000000..5fbfa919a --- /dev/null +++ b/test/libsolidity/syntaxTests/types/hex_literal_bitnot.sol @@ -0,0 +1,5 @@ +contract C { + bytes32 b = ~hex"00ff11"; +} +// ---- +// TypeError 4907: (29-41): Unary operator ~ cannot be applied to type literal_string hex"00ff11"