diff --git a/test/libsolidity/ASTJSON/user_defined_operator.json b/test/libsolidity/ASTJSON/user_defined_operator.json new file mode 100644 index 000000000..a759d0e5e --- /dev/null +++ b/test/libsolidity/ASTJSON/user_defined_operator.json @@ -0,0 +1,663 @@ +{ + "absolutePath": "a", + "exportedSymbols": + { + "C": + [ + 49 + ], + "I8": + [ + 2 + ], + "sub": + [ + 20 + ], + "unsub": + [ + 30 + ] + }, + "id": 50, + "nodeType": "SourceUnit", + "nodes": + [ + { + "canonicalName": "I8", + "id": 2, + "name": "I8", + "nameLocation": "5:2:1", + "nodeType": "UserDefinedValueTypeDefinition", + "src": "0:16:1", + "underlyingType": + { + "id": 1, + "name": "int8", + "nodeType": "ElementaryTypeName", + "src": "11:4:1", + "typeDescriptions": + { + "typeIdentifier": "t_int8", + "typeString": "int8" + } + } + }, + { + "functionList": + [ + { + "function": + { + "id": 3, + "name": "sub", + "nameLocations": + [ + "24:3:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 20, + "src": "24:3:1" + }, + "operator": "-" + }, + { + "function": + { + "id": 4, + "name": "unsub", + "nameLocations": + [ + "34:5:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 30, + "src": "34:5:1" + }, + "operator": "-" + } + ], + "global": true, + "id": 7, + "nodeType": "UsingForDirective", + "src": "17:43:1", + "typeName": + { + "id": 6, + "nodeType": "UserDefinedTypeName", + "pathNode": + { + "id": 5, + "name": "I8", + "nameLocations": + [ + "50:2:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2, + "src": "50:2:1" + }, + "referencedDeclaration": 2, + "src": "50:2:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + } + }, + { + "body": + { + "id": 19, + "nodeType": "Block", + "src": "100:2:1", + "statements": [] + }, + "id": 20, + "implemented": true, + "kind": "freeFunction", + "modifiers": [], + "name": "sub", + "nameLocation": "70:3:1", + "nodeType": "FunctionDefinition", + "parameters": + { + "id": 14, + "nodeType": "ParameterList", + "parameters": + [ + { + "constant": false, + "id": 10, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 20, + "src": "74:2:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + }, + "typeName": + { + "id": 9, + "nodeType": "UserDefinedTypeName", + "pathNode": + { + "id": 8, + "name": "I8", + "nameLocations": + [ + "74:2:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2, + "src": "74:2:1" + }, + "referencedDeclaration": 2, + "src": "74:2:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 13, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 20, + "src": "78:2:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + }, + "typeName": + { + "id": 12, + "nodeType": "UserDefinedTypeName", + "pathNode": + { + "id": 11, + "name": "I8", + "nameLocations": + [ + "78:2:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2, + "src": "78:2:1" + }, + "referencedDeclaration": 2, + "src": "78:2:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "visibility": "internal" + } + ], + "src": "73:8:1" + }, + "returnParameters": + { + "id": 18, + "nodeType": "ParameterList", + "parameters": + [ + { + "constant": false, + "id": 17, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 20, + "src": "96:2:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + }, + "typeName": + { + "id": 16, + "nodeType": "UserDefinedTypeName", + "pathNode": + { + "id": 15, + "name": "I8", + "nameLocations": + [ + "96:2:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2, + "src": "96:2:1" + }, + "referencedDeclaration": 2, + "src": "96:2:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "visibility": "internal" + } + ], + "src": "95:4:1" + }, + "scope": 50, + "src": "61:41:1", + "stateMutability": "pure", + "virtual": false, + "visibility": "internal" + }, + { + "body": + { + "id": 29, + "nodeType": "Block", + "src": "140:2:1", + "statements": [] + }, + "id": 30, + "implemented": true, + "kind": "freeFunction", + "modifiers": [], + "name": "unsub", + "nameLocation": "112:5:1", + "nodeType": "FunctionDefinition", + "parameters": + { + "id": 24, + "nodeType": "ParameterList", + "parameters": + [ + { + "constant": false, + "id": 23, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 30, + "src": "118:2:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + }, + "typeName": + { + "id": 22, + "nodeType": "UserDefinedTypeName", + "pathNode": + { + "id": 21, + "name": "I8", + "nameLocations": + [ + "118:2:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2, + "src": "118:2:1" + }, + "referencedDeclaration": 2, + "src": "118:2:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "visibility": "internal" + } + ], + "src": "117:4:1" + }, + "returnParameters": + { + "id": 28, + "nodeType": "ParameterList", + "parameters": + [ + { + "constant": false, + "id": 27, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 30, + "src": "136:2:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + }, + "typeName": + { + "id": 26, + "nodeType": "UserDefinedTypeName", + "pathNode": + { + "id": 25, + "name": "I8", + "nameLocations": + [ + "136:2:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2, + "src": "136:2:1" + }, + "referencedDeclaration": 2, + "src": "136:2:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "visibility": "internal" + } + ], + "src": "135:4:1" + }, + "scope": 50, + "src": "103:39:1", + "stateMutability": "pure", + "virtual": false, + "visibility": "internal" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 49, + "linearizedBaseContracts": + [ + 49 + ], + "name": "C", + "nameLocation": "152:1:1", + "nodeType": "ContractDefinition", + "nodes": + [ + { + "body": + { + "id": 47, + "nodeType": "Block", + "src": "208:30:1", + "statements": + [ + { + "expression": + { + "commonType": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + }, + "function": 20, + "id": 45, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": + { + "function": 30, + "id": 43, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "-", + "prefix": true, + "src": "225:2:1", + "subExpression": + { + "id": 42, + "name": "a", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33, + "src": "226:1:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "nodeType": "BinaryOperation", + "operator": "-", + "rightExpression": + { + "id": 44, + "name": "b", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 36, + "src": "230:1:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "src": "225:6:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "functionReturnParameters": 41, + "id": 46, + "nodeType": "Return", + "src": "218:13:1" + } + ] + }, + "functionSelector": "ac9fe858", + "id": 48, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "169:1:1", + "nodeType": "FunctionDefinition", + "parameters": + { + "id": 37, + "nodeType": "ParameterList", + "parameters": + [ + { + "constant": false, + "id": 33, + "mutability": "mutable", + "name": "a", + "nameLocation": "174:1:1", + "nodeType": "VariableDeclaration", + "scope": 48, + "src": "171:4:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + }, + "typeName": + { + "id": 32, + "nodeType": "UserDefinedTypeName", + "pathNode": + { + "id": 31, + "name": "I8", + "nameLocations": + [ + "171:2:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2, + "src": "171:2:1" + }, + "referencedDeclaration": 2, + "src": "171:2:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 36, + "mutability": "mutable", + "name": "b", + "nameLocation": "180:1:1", + "nodeType": "VariableDeclaration", + "scope": 48, + "src": "177:4:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + }, + "typeName": + { + "id": 35, + "nodeType": "UserDefinedTypeName", + "pathNode": + { + "id": 34, + "name": "I8", + "nameLocations": + [ + "177:2:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2, + "src": "177:2:1" + }, + "referencedDeclaration": 2, + "src": "177:2:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "visibility": "internal" + } + ], + "src": "170:12:1" + }, + "returnParameters": + { + "id": 41, + "nodeType": "ParameterList", + "parameters": + [ + { + "constant": false, + "id": 40, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 48, + "src": "204:2:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + }, + "typeName": + { + "id": 39, + "nodeType": "UserDefinedTypeName", + "pathNode": + { + "id": 38, + "name": "I8", + "nameLocations": + [ + "204:2:1" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2, + "src": "204:2:1" + }, + "referencedDeclaration": 2, + "src": "204:2:1", + "typeDescriptions": + { + "typeIdentifier": "t_userDefinedValueType$_I8_$2", + "typeString": "I8" + } + }, + "visibility": "internal" + } + ], + "src": "203:4:1" + }, + "scope": 49, + "src": "160:78:1", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 50, + "src": "143:97:1", + "usedErrors": [] + } + ], + "src": "0:241:1" +} diff --git a/test/libsolidity/ASTJSON/user_defined_operator.sol b/test/libsolidity/ASTJSON/user_defined_operator.sol new file mode 100644 index 000000000..df5d0ed32 --- /dev/null +++ b/test/libsolidity/ASTJSON/user_defined_operator.sol @@ -0,0 +1,11 @@ +type I8 is int8; +using {sub as -, unsub as -} for I8 global; +function sub(I8, I8) pure returns (I8) {} +function unsub(I8) pure returns (I8) {} +contract C { + function f(I8 a, I8 b) public pure returns (I8) { + return -a - b; + } +} + +// ---- diff --git a/test/libsolidity/analysis/FunctionCallGraph.cpp b/test/libsolidity/analysis/FunctionCallGraph.cpp index 8c10ca72a..9ace58a89 100644 --- a/test/libsolidity/analysis/FunctionCallGraph.cpp +++ b/test/libsolidity/analysis/FunctionCallGraph.cpp @@ -1702,6 +1702,72 @@ BOOST_AUTO_TEST_CASE(using_for) checkCallGraphExpectations(get<1>(graphs), expectedDeployedEdges); } +BOOST_AUTO_TEST_CASE(user_defined_binary_operator) +{ + unique_ptr compilerStack = parseAndAnalyzeContracts(R"( + type Int is int128; + using {add as +} for Int; + + function add(Int, Int) pure returns (Int) { + return Int.wrap(0); + } + + contract C { + function pub() public { + Int.wrap(0) + Int.wrap(1); + } + } + )"s); + tuple graphs = collectGraphs(*compilerStack); + + map expectedCreationEdges = { + {"C", {}}, + }; + + map expectedDeployedEdges = { + {"C", { + {"Entry", "function C.pub()"}, + {"function C.pub()", "function add(Int,Int)"}, + }}, + }; + + checkCallGraphExpectations(get<0>(graphs), expectedCreationEdges); + checkCallGraphExpectations(get<1>(graphs), expectedDeployedEdges); +} + +BOOST_AUTO_TEST_CASE(user_defined_unary_operator) +{ + unique_ptr compilerStack = parseAndAnalyzeContracts(R"( + type Int is int128; + using {sub as -} for Int; + + function sub(Int) pure returns (Int) { + return Int.wrap(0); + } + + contract C { + function pub() public { + -Int.wrap(1); + } + } + )"s); + tuple graphs = collectGraphs(*compilerStack); + + map expectedCreationEdges = { + {"C", {}}, + }; + + map expectedDeployedEdges = { + {"C", { + {"Entry", "function C.pub()"}, + {"function C.pub()", "function sub(Int)"}, + }}, + }; + + checkCallGraphExpectations(get<0>(graphs), expectedCreationEdges); + checkCallGraphExpectations(get<1>(graphs), expectedDeployedEdges); +} + BOOST_AUTO_TEST_CASE(getters) { unique_ptr compilerStack = parseAndAnalyzeContracts(R"( diff --git a/test/libsolidity/semanticTests/operators/userDefined/attaching_and_defining_operator_with_same_function.sol b/test/libsolidity/semanticTests/operators/userDefined/attaching_and_defining_operator_with_same_function.sol new file mode 100644 index 000000000..e03723a63 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/attaching_and_defining_operator_with_same_function.sol @@ -0,0 +1,20 @@ +type Int is int16; + +using {add as +, add} for Int; + +function add(Int _a, Int _b) pure returns (Int) { + return Int.wrap(Int.unwrap(_a) + Int.unwrap(_b)); +} + +contract C { + function f() pure public returns (Int) { + return Int.wrap(5) + Int.wrap(5); + } + + function g() pure public returns (Int) { + return Int.wrap(7).add(Int.wrap(6)); + } +} +// ---- +// f() -> 10 +// g() -> 13 diff --git a/test/libsolidity/semanticTests/operators/userDefined/calling_all_operators.sol b/test/libsolidity/semanticTests/operators/userDefined/calling_all_operators.sol new file mode 100644 index 000000000..b61edd168 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/calling_all_operators.sol @@ -0,0 +1,125 @@ +type Int is int128; +using { + bitor as |, bitand as &, bitxor as ^, bitnot as ~, + add as +, sub as -, unsub as -, mul as *, div as /, mod as %, + eq as ==, noteq as !=, lt as <, gt as >, leq as <=, geq as >=, + shl as <<, sar as >>, exp as **, not as ! +} for Int; + +function uw(Int x) pure returns (int128) { + return Int.unwrap(x); +} +function w(int128 x) pure returns (Int) { + return Int.wrap(x); +} +function bitor(Int, Int) pure returns (Int) { + return w(10); +} +function bitand(Int, Int) pure returns (Int) { + return w(11); +} +function bitxor(Int, Int) pure returns (Int) { + return w(12); +} +function bitnot(Int) pure returns (Int) { + return w(13); +} +function add(Int x, Int) pure returns (Int) { + return w(uw(x) + 10); +} +function sub(Int, Int) pure returns (Int) { + return w(15); +} +function unsub(Int) pure returns (Int) { + return w(16); +} +function mul(Int, Int) pure returns (Int) { + return w(17); +} +function div(Int, Int) pure returns (Int) { + return w(18); +} +function mod(Int, Int) pure returns (Int) { + return w(19); +} +function eq(Int x, Int) pure returns (bool) { + return uw(x) == 1; +} +function noteq(Int x, Int) pure returns (bool) { + return uw(x) == 2; +} +function lt(Int x, Int) pure returns (bool) { + return uw(x) < 10; +} +function gt(Int x, Int) pure returns (bool) { + return uw(x) > 10; +} +function leq(Int x, Int) pure returns (bool) { + return uw(x) <= 10; +} +function geq(Int x, Int) pure returns (bool) { + return uw(x) >= 10; +} +function shl(Int, Int) pure returns (Int) { + return w(20); +} +function sar(Int, Int) pure returns (Int) { + return w(21); +} +function exp(Int, Int) pure returns (Int) { + return w(22); +} +function not(Int) pure returns (Int) { + return w(23); +} + +contract C { + function test_bitor() public pure returns (Int) { return w(1) | w(2); } + function test_bitand() public pure returns (Int) { return w(1) & w(2); } + function test_bitxor() public pure returns (Int) { return w(1) ^ w(2); } + function test_bitnot() public pure returns (Int) { return ~w(1); } + function test_add(int128 x) public pure returns (Int) { return w(x) + w(2); } + function test_sub() public pure returns (Int) { return w(1) - w(2); } + function test_unsub() public pure returns (Int) { return -w(1); } + function test_mul() public pure returns (Int) { return w(1) * w(2); } + function test_div() public pure returns (Int) { return w(1) / w(2); } + function test_mod() public pure returns (Int) { return w(1) % w(2); } + function test_eq(int128 x) public pure returns (bool) { return w(x) == w(2); } + function test_neq(int128 x) public pure returns (bool) { return w(x) != w(2); } + function test_lt(int128 x) public pure returns (bool) { return w(x) < w(2); } + function test_gt(int128 x) public pure returns (bool) { return w(x) > w(2); } + function test_leq(int128 x) public pure returns (bool) { return w(x) <= w(2); } + function test_geq(int128 x) public pure returns (bool) { return w(x) >= w(2); } + function test_shl() public pure returns (Int) { return w(1) << w(2); } + function test_sar() public pure returns (Int) { return w(1) >> w(2); } + function test_exp() public pure returns (Int) { return w(1) ** w(2); } + function test_not() public pure returns (Int) { return !w(1); } +} +// ---- +// test_bitor() -> 10 +// test_bitand() -> 11 +// test_bitxor() -> 12 +// test_bitnot() -> 13 +// test_add(int128): 4 -> 14 +// test_add(int128): 104 -> 114 +// test_sub() -> 15 +// test_unsub() -> 16 +// test_mul() -> 17 +// test_div() -> 18 +// test_mod() -> 19 +// test_eq(int128): 1 -> true +// test_eq(int128): 2 -> false +// test_neq(int128): 2 -> true +// test_neq(int128): 1 -> false +// test_lt(int128): 9 -> true +// test_lt(int128): 10 -> false +// test_gt(int128): 11 -> true +// test_gt(int128): 10 -> false +// test_leq(int128): 10 -> true +// test_leq(int128): 11 -> false +// test_geq(int128): 10 -> true +// test_geq(int128): 9 -> false +// test_shl() -> 20 +// test_sar() -> 21 +// test_exp() -> 22 +// test_not() -> 23 diff --git a/test/libsolidity/semanticTests/operators/userDefined/calling_all_operators_precendence.sol b/test/libsolidity/semanticTests/operators/userDefined/calling_all_operators_precendence.sol new file mode 100644 index 000000000..c4a5a9b07 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/calling_all_operators_precendence.sol @@ -0,0 +1,93 @@ +type Int is int64; +using { + bitor as |, bitand as &, bitxor as ^, bitnot as ~, shl as <<, sar as >>, + add as +, sub as -, unsub as -, mul as *, div as /, mod as %, exp as **, + eq as ==, noteq as !=, + not as ! +} for Int; + +function uw(Int x) pure returns (int64) { return Int.unwrap(x); } +function w(int64 x) pure returns (Int) { return Int.wrap(x); } + +function bitor(Int x, Int y) pure returns (Int) { return w(uw(x) | uw(y)); } +function bitand(Int x, Int y) pure returns (Int) { return w(uw(x) & uw(y)); } +function bitxor(Int x, Int y) pure returns (Int) { return w(uw(x) ^ uw(y)); } +function bitnot(Int x) pure returns (Int) { return w(~uw(x)); } +function shl(Int x, Int y) pure returns (Int) { return w(uw(x) << uint64(uw(y))); } +function sar(Int x, Int y) pure returns (Int) { return w(uw(x) >> uint64(uw(y))); } + +function add(Int x, Int y) pure returns (Int) { return w(uw(x) + uw(y)); } +function sub(Int x, Int y) pure returns (Int) { return w(uw(x) - uw(y)); } +function unsub(Int x) pure returns (Int) { return w(-uw(x)); } +function mul(Int x, Int y) pure returns (Int) { return w(uw(x) * uw(y)); } +function div(Int x, Int y) pure returns (Int) { return w(uw(x) / uw(y)); } +function mod(Int x, Int y) pure returns (Int) { return w(uw(x) % uw(y)); } +function exp(Int x, Int y) pure returns (Int) { return w(uw(x) ** uint64(uw(y))); } + +function eq(Int x, Int y) pure returns (bool) { return uw(x) == uw(y); } +function noteq(Int x, Int y) pure returns (bool) { return uw(x) != uw(y); } + +function not(Int x) pure returns (Int) { return w((uw(x) == 0 ? int64(1) : int64(0))); } + +contract C { + Int constant I0 = Int.wrap(0); + Int constant I1 = Int.wrap(1); + Int constant I2 = Int.wrap(2); + Int constant I3 = Int.wrap(3); + Int constant I4 = Int.wrap(4); + Int constant I5 = Int.wrap(5); + Int constant I6 = Int.wrap(6); + Int constant I7 = Int.wrap(7); + Int constant I10 = Int.wrap(10); + Int constant I13 = Int.wrap(13); + Int constant I15 = Int.wrap(15); + Int constant I20 = Int.wrap(20); + Int constant I128 = Int.wrap(128); + + function test_bitwise() public pure { + assert(Int.unwrap(I0 & I0 | I1) == (0 & 0 | 1)); + assert(Int.unwrap(I0 & I0 | I1) == ((0 & 0) | 1)); + } + + function test_bitwise_arithmetic() public pure { + assert(Int.unwrap(I1 << I1 + I1 & ~I1 | I1 << I2 * I3 - I1 & ~I3) == (1 << 1 + 1 & ~1 | 1 << 2 * 3 - 1 & ~3)); + assert(Int.unwrap(I1 << I1 + I1 & ~I1 | I1 << I2 * I3 - I1 & ~I3) == (((1 << (1 + 1)) & (~1)) | ((1 << ((2 * 3) - 1)) & (~3)))); + } + + function test_arithmetic() public pure { + assert(Int.unwrap(I1 + I2 ** I3 / I4 - I5 % I6 * I7) == (1 + 2 ** 3 / 4 - 5 % 6 * 7)); + assert(Int.unwrap(I1 + I2 ** I3 / I4 - I5 % I6 * I7) == ((1 + ((2 ** 3) / 4)) - ((5 % 6) * 7))); + } + + function test_not() public pure { + assert((!I0 + I1) == I2); + assert((!I0 * I1) != I2); + + assert((!I0 << I2) == I4); + assert((!I0 | I3) == I3); + assert((!~-I1 + I1) == I2); + } + + function test_all() public pure { + assert( + Int.unwrap(I128 + I1 - I10 + I4 & ~I1 ^ ~I1 >> I1 + I1 << I3 ** I2 | -I15 % -I10 * I20 / I2 + I13 & ~I3) == + (128 + 1 - 10 + 4 & ~1 ^ ~1 >> 1 + 1 << 3 ** 2 | -15 % -10 * 20 / 2 + 13 & ~3) + ); + assert( + Int.unwrap(I128 + I1 - I10 + I4 & ~I1 ^ ~I1 >> I1 + I1 << I3 ** I2 | -I15 % -I10 * I20 / I2 + I13 & ~I3) == + ( + ( + ((((128 + 1) - 10) + 4) & (~1)) ^ + (((~1) >> (1 + 1)) << (3 ** 2)) + ) | + ((((((-15) % (-10)) * 20) / 2) + 13) & (~3)) + ) + ); + } +} +// ---- +// test_bitwise() -> +// test_bitwise_arithmetic() -> +// test_arithmetic() -> +// test_not() -> +// test_all() -> diff --git a/test/libsolidity/semanticTests/operators/userDefined/calling_operator_consecutive_calls_udvt.sol b/test/libsolidity/semanticTests/operators/userDefined/calling_operator_consecutive_calls_udvt.sol new file mode 100644 index 000000000..5a0df026c --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/calling_operator_consecutive_calls_udvt.sol @@ -0,0 +1,18 @@ +type A is address; + +using {add as +} for A; + +function add(A a, A b) pure returns (A) { + return A.wrap(address(uint160(A.unwrap(a)) + uint160(A.unwrap(b)))); +} + +contract C { + function g() public pure returns (A) { + A a = A.wrap(0x3333333333333333333333333333333333333333); + A b = A.wrap(0x1111111111111111111111111111111111111111); + A c = A.wrap(0x5555555555555555555555555555555555555555); + return a + b + c; + } +} +// ---- +// g() -> 0x9999999999999999999999999999999999999999 diff --git a/test/libsolidity/semanticTests/operators/userDefined/calling_operator_that_makes_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/calling_operator_that_makes_external_call.sol new file mode 100644 index 000000000..c8f32e6f5 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/calling_operator_that_makes_external_call.sol @@ -0,0 +1,26 @@ +type Int is int16; + +using {add as +} for Int; + + +function add(Int, Int) returns (Int) { + B b = new B(); + return b.f(); +} + +contract B { + Int s; + function f() external returns (Int) { + s = Int.wrap(3); + return s; + } +} + +contract C { + function test() public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} +// ---- +// test() -> 3 +// gas legacy: 119695 diff --git a/test/libsolidity/semanticTests/operators/userDefined/calling_transitively_imported_global_operator.sol b/test/libsolidity/semanticTests/operators/userDefined/calling_transitively_imported_global_operator.sol new file mode 100644 index 000000000..0f7a993e9 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/calling_transitively_imported_global_operator.sol @@ -0,0 +1,28 @@ +==== Source: s1.sol ==== +type Int is int; + +using {add1 as +} for Int global; + +function add1(Int, Int) pure returns (Int) { + return Int.wrap(3); +} + +==== Source: s2.sol ==== +import {Int} from "s1.sol"; + +using {add2 as +} for Int; + +function add2(Int, Int) pure returns (Int) { + return Int.wrap(7); +} + +==== Source: s3.sol ==== +import {Int} from "s2.sol"; + +contract C { + function f() pure public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} +// ---- +// f() -> 3 diff --git a/test/libsolidity/semanticTests/operators/userDefined/contract_level_using_for.sol b/test/libsolidity/semanticTests/operators/userDefined/contract_level_using_for.sol new file mode 100644 index 000000000..5e26b7467 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/contract_level_using_for.sol @@ -0,0 +1,40 @@ +type Int is int; + +function add1(Int, Int) pure returns (Int) { + return Int.wrap(1); +} + +function add2(Int, Int) pure returns (Int) { + return Int.wrap(2); +} + +contract C1 { + using {add1 as +} for Int; + + function f() public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} + +contract C2 { + using {add2 as +} for Int; + + function f() public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} + +contract C { + function test1() public returns (Int) { + C1 c = new C1(); + return c.f(); + } + + function test2() public returns (Int) { + C2 c = new C2(); + return c.f(); + } +} +// ---- +// test1() -> 1 +// test2() -> 2 diff --git a/test/libsolidity/semanticTests/operators/userDefined/contract_level_using_for_base_and_derived_same_operator.sol b/test/libsolidity/semanticTests/operators/userDefined/contract_level_using_for_base_and_derived_same_operator.sol new file mode 100644 index 000000000..904a7908c --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/contract_level_using_for_base_and_derived_same_operator.sol @@ -0,0 +1,41 @@ +type Int is int128; + +function addA(Int, Int) pure returns (Int) { + return Int.wrap(1); +} + +function addB(Int, Int) pure returns (Int) { + return Int.wrap(3); +} + +function addC(Int, Int) pure returns (Int) { + return Int.wrap(7); +} + +contract A { + using {addA as +} for Int; + + function testA() pure public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} + +contract B is A { + using {addB as +} for Int; + + function testB() pure public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} + +contract C is A, B { + using {addC as +} for Int; + + function testC() pure public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} +// ---- +// testA() -> 1 +// testB() -> 3 +// testC() -> 7 diff --git a/test/libsolidity/semanticTests/operators/userDefined/custom_fixed_point_type_with_operators.sol b/test/libsolidity/semanticTests/operators/userDefined/custom_fixed_point_type_with_operators.sol new file mode 100644 index 000000000..11f2a5e47 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/custom_fixed_point_type_with_operators.sol @@ -0,0 +1,22 @@ +type Fixed is int128; +using {add as +, mul as *} for Fixed; + +int constant MULTIPLIER = 10**18; + +function add(Fixed a, Fixed b) pure returns (Fixed) { + return Fixed.wrap(Fixed.unwrap(a) + Fixed.unwrap(b)); +} + +function mul(Fixed a, Fixed b) pure returns (Fixed) { + int intermediate = (int(Fixed.unwrap(a)) * int(Fixed.unwrap(b))) / MULTIPLIER; + if (int128(intermediate) != intermediate) { revert("Overflow"); } + return Fixed.wrap(int128(intermediate)); +} + +contract C { + function applyInterest(Fixed value, Fixed percentage) public pure returns (Fixed result) { + return value + value * percentage; + } +} +// ---- +// applyInterest(int128,int128): 500000000000000000000, 100000000000000000 -> 550000000000000000000 diff --git a/test/libsolidity/semanticTests/operators/userDefined/file_level_using_for_global_and_non_global.sol b/test/libsolidity/semanticTests/operators/userDefined/file_level_using_for_global_and_non_global.sol new file mode 100644 index 000000000..26a11fc1d --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/file_level_using_for_global_and_non_global.sol @@ -0,0 +1,29 @@ +==== Source: s1.sol ==== +type Int is int; + +using {add as +} for Int global; +using {add as +} for Int; + +function add(Int a, Int b) pure returns (Int) { + return Int.wrap(Int.unwrap(a) + Int.unwrap(b)); +} + +function test_add() pure returns (Int) { + return Int.wrap(1) + Int.wrap(2); +} + +==== Source: s2.sol ==== +import "s1.sol"; + +contract C2 { + function test1() pure public returns (Int) { + return test_add(); + } + + function test2() pure public returns (Int) { + return Int.wrap(3) + Int.wrap(4); + } +} +// ---- +// test1() -> 3 +// test2() -> 7 diff --git a/test/libsolidity/semanticTests/operators/userDefined/file_level_using_for_global_with_unary_operator_and_non_global_with_binary_operator_same_file.sol b/test/libsolidity/semanticTests/operators/userDefined/file_level_using_for_global_with_unary_operator_and_non_global_with_binary_operator_same_file.sol new file mode 100644 index 000000000..fe9c4133e --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/file_level_using_for_global_with_unary_operator_and_non_global_with_binary_operator_same_file.sol @@ -0,0 +1,25 @@ +type Int is int16; + +using {unsub as -} for Int global; +using {sub as -} for Int; + +function sub(Int a, Int b) pure returns (Int) { + return Int.wrap(Int.unwrap(a) - Int.unwrap(b)); +} + +function unsub(Int a) pure returns (Int) { + return Int.wrap(-Int.unwrap(a)); +} + +contract C { + function test_sub() public returns (Int) { + return Int.wrap(7) - Int.wrap(2); + } + + function test_unsub() public returns (Int) { + return -Int.wrap(4); + } +} +// ---- +// test_sub() -> 5 +// test_unsub() -> -4 diff --git a/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_function_shadowing_builtin_keccak256.sol b/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_function_shadowing_builtin_keccak256.sol new file mode 100644 index 000000000..3278fd8fd --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_function_shadowing_builtin_keccak256.sol @@ -0,0 +1,15 @@ +type Int is int16; + +using {keccak256 as +} for Int; + +function keccak256(Int a, Int b) pure returns (Int) { + return Int.wrap(Int.unwrap(a) + Int.unwrap(b)); +} + +contract C { + function test() public returns (Int) { + return Int.wrap(3) + Int.wrap(4); + } +} +// ---- +// test() -> 7 diff --git a/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_library_function.sol b/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_library_function.sol new file mode 100644 index 000000000..27961bf31 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_library_function.sol @@ -0,0 +1,30 @@ +==== Source: a.sol ==== +library L { + type Int is int128; + + function add(Int, Int) pure public returns (Int) { + return Int.wrap(7); + } + + function sub(Int) pure public returns (Int) { + return Int.wrap(5); + } +} +==== Source: b.sol ==== +import "a.sol" as a; + +contract C { + using {a.L.add as +} for a.L.Int; + using {a.L.sub as -} for a.L.Int; + + function f() pure public returns (a.L.Int) { + return a.L.Int.wrap(0) + a.L.Int.wrap(0); + } + + function g() pure public returns (a.L.Int) { + return - a.L.Int.wrap(0); + } +} +// ---- +// f() -> 7 +// g() -> 5 diff --git a/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_library_function_with_modifier.sol b/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_library_function_with_modifier.sol new file mode 100644 index 000000000..738d4ac05 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_library_function_with_modifier.sol @@ -0,0 +1,26 @@ +library L { + type Int is int128; + + error DivisionByZero(); + + modifier nonZero(Int a) { + if (Int.unwrap(a) == 0) + revert("Division by zero"); + _; + } + + function div(Int a, Int b) pure public nonZero(b) returns (Int) { + return Int.wrap(Int.unwrap(a) / Int.unwrap(b)); + } +} + +contract C { + using {L.div as /} for L.Int; + + function testDiv(L.Int a, L.Int b) pure public returns (L.Int) { + return a / b; + } +} +// ---- +// testDiv(int128,int128): 10, 2 -> 5 +// testDiv(int128,int128): 10, 0 -> FAILURE, hex"08c379a0", 0x20, 0x10, "Division by zero" diff --git a/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_transitively_imported_function.sol b/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_transitively_imported_function.sol new file mode 100644 index 000000000..9dd6facae --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/implementing_operator_with_transitively_imported_function.sol @@ -0,0 +1,22 @@ +==== Source: a.sol ==== +library L { + type Int is int128; + + function add(Int, Int) pure public returns (Int) { + return Int.wrap(7); + } +} +==== Source: b.sol ==== +import "a.sol" as a; +==== Source: c.sol ==== +import "b.sol" as b; + +contract C { + using {b.a.L.add as +} for b.a.L.Int; + + function f() pure public returns (b.a.L.Int) { + return b.a.L.Int.wrap(0) + b.a.L.Int.wrap(0); + } +} +// ---- +// f() -> 7 diff --git a/test/libsolidity/semanticTests/operators/userDefined/multiple_operator_definitions_different_types_different_functions_separate_directives.sol b/test/libsolidity/semanticTests/operators/userDefined/multiple_operator_definitions_different_types_different_functions_separate_directives.sol new file mode 100644 index 000000000..769f1a7f2 --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/multiple_operator_definitions_different_types_different_functions_separate_directives.sol @@ -0,0 +1,26 @@ +type SmallInt is int; +type BigInt is int; + +using {addSmall as +} for SmallInt; +using {addBig as +} for BigInt; + +function addSmall(SmallInt a, SmallInt b) pure returns (SmallInt) { + return SmallInt.wrap(SmallInt.unwrap(a) + SmallInt.unwrap(b)); +} + +function addBig(BigInt a, BigInt b) pure returns (BigInt) { + return BigInt.wrap(10 * (BigInt.unwrap(a) + BigInt.unwrap(b))); +} + +contract C { + function small() public pure returns (SmallInt) { + return SmallInt.wrap(1) + SmallInt.wrap(2); + } + + function big() public pure returns (BigInt) { + return BigInt.wrap(3) + BigInt.wrap(4); + } +} +// ---- +// small() -> 3 +// big() -> 70 diff --git a/test/libsolidity/semanticTests/operators/userDefined/multiple_operator_definitions_operator_same_function_same_directive.sol b/test/libsolidity/semanticTests/operators/userDefined/multiple_operator_definitions_operator_same_function_same_directive.sol new file mode 100644 index 000000000..4d1e75f3c --- /dev/null +++ b/test/libsolidity/semanticTests/operators/userDefined/multiple_operator_definitions_operator_same_function_same_directive.sol @@ -0,0 +1,20 @@ +type Int is int32; + +using {foo as +, foo as -} for Int; + +function foo(Int a, Int b) pure returns(Int) { + return Int.wrap(Int.unwrap(a) + Int.unwrap(b)); +} + +contract C { + function f() pure public returns (Int) { + return Int.wrap(2) + Int.wrap(3); + } + + function g() pure public returns (Int) { + return Int.wrap(6) - Int.wrap(1); + } +} +// ---- +// f() -> 5 +// g() -> 7 diff --git a/test/libsolidity/syntaxTests/constants/constant_cyclic_via_user_operators.sol b/test/libsolidity/syntaxTests/constants/constant_cyclic_via_user_operators.sol new file mode 100644 index 000000000..e3f75ce44 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/constant_cyclic_via_user_operators.sol @@ -0,0 +1,10 @@ +type Type is uint; +using {f as +} for Type; +function f(Type, Type) pure returns (Type) {} + +Type constant t = Type.wrap(1); +Type constant u = v + t; +Type constant v = u + t; +// ---- +// TypeError 8349: (141-146): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (166-171): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/controlFlow/userDefinedOperators/binary_operator_udvt.sol b/test/libsolidity/syntaxTests/controlFlow/userDefinedOperators/binary_operator_udvt.sol new file mode 100644 index 000000000..a1e002184 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/userDefinedOperators/binary_operator_udvt.sol @@ -0,0 +1,17 @@ +type X is uint24; +type Y is uint16; + +using {addX as +} for X; +using {addY as +} for Y; + +function addX(X, X) pure returns (X) {} +function addY(Y, Y) pure returns (Y) { revert(); } + +contract C { + function f() public pure { + X.wrap(1) + X.wrap(Y.unwrap(Y.wrap(2) + Y.wrap(3))); + X.wrap(4) + X.wrap(5); // Unreachable + } +} +// ---- +// Warning 5740: (293-314): Unreachable code. diff --git a/test/libsolidity/syntaxTests/controlFlow/userDefinedOperators/unary_operator_udvt.sol b/test/libsolidity/syntaxTests/controlFlow/userDefinedOperators/unary_operator_udvt.sol new file mode 100644 index 000000000..dbbd65a16 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/userDefinedOperators/unary_operator_udvt.sol @@ -0,0 +1,17 @@ +type X is uint24; +type Y is uint16; + +using {unsubX as -} for X; +using {unsubY as -} for Y; + +function unsubX(X) pure returns (X) {} +function unsubY(Y) pure returns (Y) { revert(); } + +contract C { + function f() public pure { + -X.wrap(Y.unwrap(-Y.wrap(1))); + -X.wrap(Y.unwrap(Y.wrap(2))); // Unreachable + } +} +// ---- +// Warning 5740: (273-301): Unreachable code. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol index 930e79a3b..1cf46ac83 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol @@ -7,4 +7,4 @@ contract test { } } // ---- -// TypeError 2271: (79-85): Built-in binary operator == cannot be applied to types struct test.s storage ref and struct test.s storage ref. +// TypeError 2271: (79-85): Built-in binary operator == cannot be applied to types struct test.s storage ref and struct test.s storage ref. No matching user-defined operator found. diff --git a/test/libsolidity/syntaxTests/operators/calling_operator_binary_user_defined_not_available.sol b/test/libsolidity/syntaxTests/operators/calling_operator_binary_user_defined_not_available.sol new file mode 100644 index 000000000..ea0c8f9d8 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/calling_operator_binary_user_defined_not_available.sol @@ -0,0 +1,11 @@ +type Int is int256; + +function f() pure { + Int a = Int.wrap(0); + a + a; + a >>> a; +} + +// ---- +// TypeError 2271: (70-75): Built-in binary operator + cannot be applied to types Int and Int. No matching user-defined operator found. +// TypeError 2271: (81-88): Built-in binary operator >>> cannot be applied to types Int and Int. diff --git a/test/libsolidity/syntaxTests/operators/calling_operator_unary_user_defined_not_available.sol b/test/libsolidity/syntaxTests/operators/calling_operator_unary_user_defined_not_available.sol new file mode 100644 index 000000000..29273852e --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/calling_operator_unary_user_defined_not_available.sol @@ -0,0 +1,11 @@ +type Int is int256; + +function f() pure { + Int a = Int.wrap(0); + -a; + a++; +} + +// ---- +// TypeError 4907: (70-72): Built-in unary operator - cannot be applied to type Int. No matching user-defined operator found. +// TypeError 9767: (78-81): Built-in unary operator ++ cannot be applied to type Int. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_as_attached_function_via_function_name.sol b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_as_attached_function_via_function_name.sol new file mode 100644 index 000000000..7fc33ca72 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_as_attached_function_via_function_name.sol @@ -0,0 +1,12 @@ +type Int is int16; + +using {add as +} for Int; + +function add(Int, Int) pure returns (Int) {} + +function f() { + Int a; + a.add(a); +} +// ---- +// TypeError 9582: (123-128): Member "add" not found or not visible after argument-dependent lookup in Int. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_as_attached_function_via_operator_name.sol b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_as_attached_function_via_operator_name.sol new file mode 100644 index 000000000..4f2d3400b --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_as_attached_function_via_operator_name.sol @@ -0,0 +1,12 @@ +type Int is int16; + +using {add as +} for Int; + +function add(Int, Int) pure returns (Int) {} + +function f() { + Int a; + a.+(a); +} +// ---- +// ParserError 2314: (125-126): Expected identifier but got '+' diff --git a/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_imported_global_non_global.sol b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_imported_global_non_global.sol new file mode 100644 index 000000000..65e536947 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_imported_global_non_global.sol @@ -0,0 +1,18 @@ +==== Source: s1.sol ==== +type Int is int; +using {add as +} for Int global; +using {sub as -} for Int; + +function add(Int, Int) pure returns (Int) {} +function sub(Int, Int) pure returns (Int) {} + +==== Source: s2.sol ==== +import "s1.sol"; +contract C { + function f() pure public { + Int.wrap(0) + Int.wrap(0); + Int.wrap(0) - Int.wrap(0); + } +} +// ---- +// TypeError 2271: (s2.sol:104-129): Built-in binary operator - cannot be applied to types Int and Int. No matching user-defined operator found. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_imported_transitively_non_global.sol b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_imported_transitively_non_global.sol new file mode 100644 index 000000000..2d850a115 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_imported_transitively_non_global.sol @@ -0,0 +1,25 @@ +==== Source: s0.sol ==== +type Int is int; + +==== Source: s1.sol ==== +import "s0.sol"; +using {add1 as +} for Int; + +function add1(Int, Int) pure returns (Int) {} + +==== Source: s2.sol ==== +import "s0.sol"; +using {add2 as +} for Int; + +function add2(Int, Int) pure returns (Int) {} + +==== Source: s3.sol ==== +import "s1.sol"; +import "s2.sol"; +contract C { + function f() public { + Int.wrap(0) + Int.wrap(0); + } +} +// ---- +// TypeError 2271: (s3.sol:81-106): Built-in binary operator + cannot be applied to types Int and Int. No matching user-defined operator found. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_with_implicit_conversion.sol b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_with_implicit_conversion.sol new file mode 100644 index 000000000..e8789b1f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/calling_operator_with_implicit_conversion.sol @@ -0,0 +1,32 @@ +using {add as +, unsub as -} for U; + +type U is uint; + +function add(U, U) pure returns (U) {} +function unsub(U) pure returns (U) {} + +contract C { + function fromBool() public { + U u; + + u + true; + true + u; + -true; + } + + function fromUint() public { + U u; + uint32 u32; + + u + u32; + u32 + u; + -u32; + } +} +// ---- +// TypeError 5653: (200-208): The type of the second operand of this user-defined binary operator + does not match the type of the first operand, which is U. +// TypeError 2271: (218-226): Built-in binary operator + cannot be applied to types bool and U. +// TypeError 4907: (236-241): Built-in unary operator - cannot be applied to type bool. +// TypeError 5653: (325-332): The type of the second operand of this user-defined binary operator + does not match the type of the first operand, which is U. +// TypeError 2271: (342-349): Built-in binary operator + cannot be applied to types uint32 and U. +// TypeError 4907: (359-363): Built-in unary operator - cannot be applied to type uint32. Unary negation is only allowed for signed integers. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_builtin_types.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_builtin_types.sol new file mode 100644 index 000000000..1258fa71c --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_builtin_types.sol @@ -0,0 +1,13 @@ +using {f as +} for uint; +using {f as +} for uint[2]; +using {f as +} for mapping(uint => uint); +using {f as +} for function (uint) pure returns (uint); +using {f as +} for string; + +function f(uint, uint) pure returns (uint) {} +// ---- +// TypeError 5332: (7-8): Operators can only be implemented for user-defined value types. +// TypeError 5332: (32-33): Operators can only be implemented for user-defined value types. +// TypeError 5332: (60-61): Operators can only be implemented for user-defined value types. +// TypeError 5332: (102-103): Operators can only be implemented for user-defined value types. +// TypeError 5332: (158-159): Operators can only be implemented for user-defined value types. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_contract.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_contract.sol new file mode 100644 index 000000000..7996139ea --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_contract.sol @@ -0,0 +1,11 @@ +using {fc as +} for C; +using {fa as +} for A; + +function fc(C, C) returns (C) {} +function fa(A, A) returns (A) {} + +contract C {} +abstract contract A {} +// ---- +// TypeError 5332: (7-9): Operators can only be implemented for user-defined value types. +// TypeError 5332: (30-32): Operators can only be implemented for user-defined value types. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_enum.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_enum.sol new file mode 100644 index 000000000..8ec8a06ed --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_enum.sol @@ -0,0 +1,10 @@ +using {add as +} for E; + +enum E { + E1, + E2 +} + +function add(E, E) pure returns (E) {} +// ---- +// TypeError 5332: (7-10): Operators can only be implemented for user-defined value types. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_error.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_error.sol new file mode 100644 index 000000000..ddd35ea95 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_error.sol @@ -0,0 +1,10 @@ +using {add as +} for E; + +error E(); + +function add(E, E) pure returns (E) { + return E.E1; +} + +// ---- +// TypeError 5172: (21-22): Name has to refer to a user-defined type. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_event.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_event.sol new file mode 100644 index 000000000..7d808faa8 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_event.sol @@ -0,0 +1,10 @@ +using {add as +} for C.Event; + +contract C { + event Event(); +} + +function add(C.Event, C.Event) pure returns (C.Event) {} + +// ---- +// TypeError 5172: (21-28): Name has to refer to a user-defined type. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_interface.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_interface.sol new file mode 100644 index 000000000..6dfc0f862 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_interface.sol @@ -0,0 +1,7 @@ +using {f as +} for I; + +function f(I, I) returns (I) {} + +interface I {} +// ---- +// TypeError 5332: (7-8): Operators can only be implemented for user-defined value types. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_library.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_library.sol new file mode 100644 index 000000000..4ab32f5a3 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_library.sol @@ -0,0 +1,6 @@ +using {f as +} for L; + +function f() {} +library L {} +// ---- +// TypeError 1130: (19-20): Invalid use of a library name. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_struct.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_struct.sol new file mode 100644 index 000000000..6d4ba84a8 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_struct.sol @@ -0,0 +1,9 @@ +using {add as +} for S; + +struct S { + uint x; +} + +function add(S memory, S memory) pure returns (S memory) {} +// ---- +// TypeError 5332: (7-10): Operators can only be implemented for user-defined value types. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_wildcard_type_at_contract_level.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_wildcard_type_at_contract_level.sol new file mode 100644 index 000000000..c18c4467c --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_wildcard_type_at_contract_level.sol @@ -0,0 +1,9 @@ +type Int is int; + +function add(Int, Int) returns (Int) {} + +contract C { + using {add as +} for *; +} +// ---- +// SyntaxError 3349: (76-99): The type has to be specified explicitly when attaching specific functions. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_wildcard_type_at_file_level.sol b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_wildcard_type_at_file_level.sol new file mode 100644 index 000000000..d7102b893 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/defining_operator_for_wildcard_type_at_file_level.sol @@ -0,0 +1,5 @@ +using {add as +} for *; + +function add(int, int) returns (int) {} +// ---- +// SyntaxError 8118: (0-23): The type has to be specified explicitly at file level (cannot use '*'). diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_attached_free_function.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_attached_free_function.sol new file mode 100644 index 000000000..0a6daba69 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_attached_free_function.sol @@ -0,0 +1,9 @@ +type Int is uint; +using {f} for Int; + +Int constant v; +using {v.f as +} for Int; + +function f(Int) pure returns (Int) {} +// ---- +// DeclarationError 7920: (61-64): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_builtin_abi_encode.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_builtin_abi_encode.sol new file mode 100644 index 000000000..9be775582 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_builtin_abi_encode.sol @@ -0,0 +1,8 @@ +type Int is int16; + +using {abi.encode as +} for Int; + +function f(Int, Int) pure returns (Int) {} + +// ---- +// DeclarationError 7920: (27-37): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_builtin_keccak256.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_builtin_keccak256.sol new file mode 100644 index 000000000..acb8383ea --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_builtin_keccak256.sol @@ -0,0 +1,5 @@ +type Int is int16; + +using {keccak256 as +} for Int; +// ---- +// TypeError 8187: (27-36): Expected function name. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_builtin_revert.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_builtin_revert.sol new file mode 100644 index 000000000..485c52ca6 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_builtin_revert.sol @@ -0,0 +1,5 @@ +type Int is int16; + +using {revert as +} for Int; +// ---- +// DeclarationError 7920: (27-33): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_contract_function_at_contract_level.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_contract_function_at_contract_level.sol new file mode 100644 index 000000000..447242190 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_contract_function_at_contract_level.sol @@ -0,0 +1,9 @@ +type Int is int; + +contract C { + using {add as +} for Int; + + function add(Int, Int) public returns (Int) {} +} +// ---- +// TypeError 4167: (42-45): Only file-level functions and library functions can be attached to a type in a "using" statement diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_contract_function_at_file_level.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_contract_function_at_file_level.sol new file mode 100644 index 000000000..8f7578f2d --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_contract_function_at_file_level.sol @@ -0,0 +1,11 @@ +type Int is int; + +using {C.add as +} for Int; + +contract C { + function add(Int, Int) public returns (Int) { + return 0; + } +} +// ---- +// TypeError 4167: (25-30): Only file-level functions and library functions can be attached to a type in a "using" statement diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_error.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_error.sol new file mode 100644 index 000000000..35658c8ca --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_error.sol @@ -0,0 +1,7 @@ +type Int is int16; + +using {IntError as +} for Int; + +error IntError(Int a, Int b); +// ---- +// TypeError 8187: (27-35): Expected function name. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_event.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_event.sol new file mode 100644 index 000000000..b880b8565 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_event.sol @@ -0,0 +1,9 @@ +type Int is int16; + +using {C.IntEvent as +} for Int; + +contract C { + event IntEvent(Int a, Int b); +} +// ---- +// TypeError 8187: (27-37): Expected function name. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_function_pointer.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_function_pointer.sol new file mode 100644 index 000000000..f360deb3f --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_function_pointer.sol @@ -0,0 +1,8 @@ +type Int is int8; + +contract C { + function(Int, Int) external returns (Int) ptr; + using {ptr as +} for Int; +} +// ---- +// TypeError 8187: (94-97): Expected function name. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_function_shadowing_builtin_keccak256.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_function_shadowing_builtin_keccak256.sol new file mode 100644 index 000000000..6cdee2726 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_function_shadowing_builtin_keccak256.sol @@ -0,0 +1,9 @@ +type Int is int16; + +using {keccak256 as +} for Int; + +function keccak256(Int, Int) pure returns (Int) { + return Int.wrap(0); +} +// ---- +// Warning 2319: (53-128): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_library_function_external.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_library_function_external.sol new file mode 100644 index 000000000..5f51e2a5f --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_library_function_external.sol @@ -0,0 +1,11 @@ +type Int is int128; + +library L { + function externalOperator(Int, Int) external returns (Int) {} +} + +// FIXME: Not being able to use external library functions in 'using for' is a bug. +// https://github.com/ethereum/solidity/issues/13765 +using {L.externalOperator as +} for Int; +// ---- +// DeclarationError 7920: (246-264): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_library_function_private_at_contract_level.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_library_function_private_at_contract_level.sol new file mode 100644 index 000000000..cfeb089c1 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_library_function_private_at_contract_level.sol @@ -0,0 +1,6 @@ +type Int is int128; + +library L { + using {L.privateOperator as +} for Int; + function privateOperator(Int, Int) private pure returns (Int) {} +} diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_library_function_public_internal_or_private.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_library_function_public_internal_or_private.sol new file mode 100644 index 000000000..1c66c0ae6 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_library_function_public_internal_or_private.sol @@ -0,0 +1,13 @@ +type Int is int128; + +library L { + function publicOperator(Int, Int) public pure returns (Int) {} + function internalOperator(Int, Int) internal pure returns (Int) {} + function privateOperator(Int, Int) private pure returns (Int) {} +} + +using {L.publicOperator as +} for Int; +using {L.internalOperator as +} for Int; +// FIXME: Being able to use private library functions in a file-level 'using for' is a bug. +// See: https://github.com/ethereum/solidity/issues/13764 +using {L.privateOperator as +} for Int; diff --git a/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_overloaded_function.sol b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_overloaded_function.sol new file mode 100644 index 000000000..4064f13a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/implementing_operator_with_overloaded_function.sol @@ -0,0 +1,10 @@ +using {add as +} for A; +using {add as +} for AP; + +function add(A, A) pure returns (A) {} +function add(AP, AP) pure returns (AP) {} + +type A is address; +type AP is address payable; +// ---- +// DeclarationError 7920: (7-10): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_global_and_non_global_binary.sol b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_global_and_non_global_binary.sol new file mode 100644 index 000000000..8d3cea05d --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_global_and_non_global_binary.sol @@ -0,0 +1,13 @@ +type Int is int; + +using {add as +} for Int global; +using {another_add as +} for Int; + +function add(Int, Int) pure returns (Int) {} +function another_add(Int, Int) pure returns (Int) {} + +function test() pure returns (Int) { + return Int.wrap(1) + Int.wrap(2); +} +// ---- +// TypeError 5583: (233-258): User-defined binary operator + has more than one definition matching the operand types visible in the current scope. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_global_and_non_global_different_files.sol b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_global_and_non_global_different_files.sol new file mode 100644 index 000000000..c033c5725 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_global_and_non_global_different_files.sol @@ -0,0 +1,19 @@ +==== Source: Int.sol ==== +type Int is int; + +using {add as +} for Int global; + +function add(Int, Int) pure returns (Int) {} + +==== Source: test.sol ==== +import "Int.sol"; + +using {another_add as +} for Int; + +function another_add(Int, Int) pure returns (Int) {} + +function test() pure returns (Int) { + return Int.wrap(0) + Int.wrap(0); +} +// ---- +// TypeError 5583: (test.sol:156-181): User-defined binary operator + has more than one definition matching the operand types visible in the current scope. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_global_and_non_global_unary.sol b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_global_and_non_global_unary.sol new file mode 100644 index 000000000..2e9088f86 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_global_and_non_global_unary.sol @@ -0,0 +1,13 @@ +type Int is int; + +using {unsub as -} for Int global; +using {another_unsub as -} for Int; + +function unsub(Int) pure returns (Int) {} +function another_unsub(Int) pure returns (Int) {} + +function test() pure returns (Int) { + return -Int.wrap(2); +} +// ---- +// TypeError 4705: (231-243): User-defined unary operator - has more than one definition matching the operand type visible in the current scope. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_same_directive.sol b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_same_directive.sol new file mode 100644 index 000000000..09749664a --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_same_directive.sol @@ -0,0 +1,12 @@ +type Int is uint128; + +using {add as +, sub as +} for Int; + +function add(Int, Int) pure returns (Int) {} +function sub(Int, Int) pure returns (Int) {} + +function test() { + Int.wrap(0) + Int.wrap(1); +} +// ---- +// TypeError 5583: (172-197): User-defined binary operator + has more than one definition matching the operand types visible in the current scope. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_same_directive_operator_not_used.sol b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_same_directive_operator_not_used.sol new file mode 100644 index 000000000..00f3e782c --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_different_functions_same_directive_operator_not_used.sol @@ -0,0 +1,10 @@ +type Int is uint128; + +// No error if the operator is not actually used +using {add1 as +, add2 as +} for Int; +using {unsub1 as -, unsub2 as -} for Int; + +function add1(Int, Int) pure returns (Int) {} +function add2(Int, Int) pure returns (Int) {} +function unsub1(Int) pure returns (Int) {} +function unsub2(Int) pure returns (Int) {} diff --git a/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_on_file_and_contract_level.sol b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_on_file_and_contract_level.sol new file mode 100644 index 000000000..4145b3935 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_on_file_and_contract_level.sol @@ -0,0 +1,22 @@ +type Int is int; + +using {add as +} for Int; + +function add(Int, Int) pure returns (Int) {} +function another_add(Int, Int) pure returns (Int) {} + +contract B { + using {another_add as +} for Int; + + function f() public { + Int.wrap(0) + Int.wrap(0); + } +} + +contract C is B { + function g() public { + Int.wrap(0) + Int.wrap(0); + } +} +// ---- +// TypeError 5583: (230-255): User-defined binary operator + has more than one definition matching the operand types visible in the current scope. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_same_function_same_directive.sol b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_same_function_same_directive.sol new file mode 100644 index 000000000..4d3b8dbf7 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_same_function_same_directive.sol @@ -0,0 +1,9 @@ +type Int is int32; + +using {add as +, add as +} for Int; + +function add(Int, Int) pure returns(Int) {} + +function f(int32 a, int32 b) pure { + Int.wrap(a) + Int.wrap(b); +} diff --git a/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_same_function_separate_directives.sol b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_same_function_separate_directives.sol new file mode 100644 index 000000000..a200b6e94 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/multiple_operator_definitions_same_function_separate_directives.sol @@ -0,0 +1,10 @@ +type Int is int32; + +using {add as +} for Int; +using {add as +} for Int; + +function add(Int, Int) pure returns(Int) {} + +function f(int32 a, int32 b) pure { + Int.wrap(a) + Int.wrap(b); +} diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_overloading.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_overloading.sol new file mode 100644 index 000000000..3d9994d9e --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_overloading.sol @@ -0,0 +1,13 @@ +type Int is uint128; + +using {add as +, add128 as +} for Int; + +function add(Int, Int) pure returns (Int) {} +function add128(Int, int128) pure returns (Int) {} + +function test() { + Int.wrap(0) + Int.wrap(1); +} +// ---- +// TypeError 1884: (122-135): Wrong parameters in operator definition. The function "add128" needs to have two parameters of type Int and the same data location to be used for the operator +. +// TypeError 5583: (181-206): User-defined binary operator + has more than one definition matching the operand types visible in the current scope. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_function_name_missing.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_function_name_missing.sol new file mode 100644 index 000000000..3f724df6d --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_function_name_missing.sol @@ -0,0 +1,3 @@ +using {as -} for uint; +// ---- +// ParserError 2314: (7-9): Expected identifier but got 'as' diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_no_brace.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_no_brace.sol new file mode 100644 index 000000000..0478d6428 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_no_brace.sol @@ -0,0 +1,3 @@ +using f as - for uint; +// ---- +// ParserError 2314: (8-10): Expected 'for' but got 'as' diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_non_user_definable.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_non_user_definable.sol new file mode 100644 index 000000000..d55b8370e --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_non_user_definable.sol @@ -0,0 +1,16 @@ +using { + f as ++, + f as --, + f as x, + f as delete, + f as new, + f as () +} for int256; +// ---- +// ParserError 4403: (17-19): Not a user-definable operator: ++. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, ! +// ParserError 4403: (30-32): Not a user-definable operator: --. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, ! +// ParserError 4403: (43-44): Not a user-definable operator: x. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, ! +// ParserError 4403: (55-61): Not a user-definable operator: delete. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, ! +// ParserError 4403: (72-75): Not a user-definable operator: new. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, ! +// ParserError 4403: (86-87): Not a user-definable operator: (. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, ! +// ParserError 2314: (87-88): Expected '}' but got ')' diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_operator_name_missing.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_operator_name_missing.sol new file mode 100644 index 000000000..1bc8a9416 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_operator_name_missing.sol @@ -0,0 +1,4 @@ +using {f as} for uint; +// ---- +// ParserError 4403: (11-12): Not a user-definable operator: }. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, ! +// ParserError 2314: (13-16): Expected '}' but got 'for' diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_operator_named_as.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_operator_named_as.sol new file mode 100644 index 000000000..e8a5b1b3f --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_parsing_operator_named_as.sol @@ -0,0 +1,3 @@ +using {f as as} for uint; +// ---- +// ParserError 4403: (12-14): Not a user-definable operator: as. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, ! diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_returning_wrong_types.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_returning_wrong_types.sol new file mode 100644 index 000000000..c01bbdb8a --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_returning_wrong_types.sol @@ -0,0 +1,33 @@ +type Int is int256; + +using { + add as +, + div as /, + unsub as -, + bitnot as ~, + gt as >, + lt as < +} for Int; + +function add(Int x, Int y) pure returns (int256) {} +function div(Int x, Int y) pure {} +function unsub(Int) pure returns (Int, Int) {} +function bitnot(Int) pure returns (int256) {} +function gt(Int, Int) pure returns (Int) {} +function lt(Int, Int) pure returns (bool, Int) {} + +function f() pure { + Int.wrap(0) + Int.wrap(1); + Int.wrap(0) / Int.wrap(0); + -Int.wrap(0); + ~Int.wrap(0); + Int.wrap(0) < Int.wrap(0); + Int.wrap(0) > Int.wrap(0); +} +// ---- +// TypeError 7743: (167-175): Wrong return parameters in operator definition. The function "add" needs to return exactly one value of type Int to be used for the operator +. +// TypeError 7743: (211-211): Wrong return parameters in operator definition. The function "div" needs to return exactly one value of type Int to be used for the operator /. +// TypeError 7743: (247-257): Wrong return parameters in operator definition. The function "unsub" needs to return exactly one value of type Int to be used for the operator -. +// TypeError 7743: (295-303): Wrong return parameters in operator definition. The function "bitnot" needs to return exactly one value of type Int to be used for the operator ~. +// TypeError 7743: (342-347): Wrong return parameters in operator definition. The function "gt" needs to return exactly one value of type bool to be used for the operator >. +// TypeError 7743: (386-397): Wrong return parameters in operator definition. The function "lt" needs to return exactly one value of type bool to be used for the operator <. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_and_returning_types_not_matching_using_for.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_and_returning_types_not_matching_using_for.sol new file mode 100644 index 000000000..4f3d2bef8 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_and_returning_types_not_matching_using_for.sol @@ -0,0 +1,26 @@ +type Int is int256; + +using { + add as +, + sub as -, + div as / +} for Int; + +function add(Int) pure returns (Int) {} +function sub(Int, Int, Int) pure returns (Int) {} +function div(int256, int256) pure returns (Int) {} + +function f() pure { + Int.wrap(0) + Int.wrap(1); + Int.wrap(0) - Int.wrap(0); + Int.wrap(0) / Int.wrap(0); +} + +// ---- +// TypeError 1884: (94-99): Wrong parameters in operator definition. The function "add" needs to have two parameters of type Int and the same data location to be used for the operator +. +// TypeError 1884: (134-149): Wrong parameters in operator definition. The function "sub" needs to have one or two parameters of type Int and the same data location to be used for the operator -. +// TypeError 1884: (184-200): Wrong parameters in operator definition. The function "div" needs to have one or two parameters of type Int and the same data location to be used for the operator /. +// TypeError 7743: (214-219): Wrong return parameters in operator definition. The function "div" needs to return a value of the same type and data location as its parameters to be used for the operator /. +// TypeError 2271: (248-273): Built-in binary operator + cannot be applied to types Int and Int. No matching user-defined operator found. +// TypeError 2271: (279-304): Built-in binary operator - cannot be applied to types Int and Int. No matching user-defined operator found. +// TypeError 2271: (310-335): Built-in binary operator / cannot be applied to types Int and Int. No matching user-defined operator found. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_no_parameters_binary.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_no_parameters_binary.sol new file mode 100644 index 000000000..cfaaa82ec --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_no_parameters_binary.sol @@ -0,0 +1,11 @@ +type Int is int; + +using { + f as + +} for Int; + +function f() returns (Int) { + return Int.wrap(0); +} +// ---- +// TypeError 4731: (30-31): The function "f" does not have any parameters, and therefore cannot be attached to the type "Int". diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_no_parameters_unary.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_no_parameters_unary.sol new file mode 100644 index 000000000..6a2f47693 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_no_parameters_unary.sol @@ -0,0 +1,11 @@ +type Int is int; + +using { + f as ~ +} for Int; + +function f() returns (Int) { + return Int.wrap(0); +} +// ---- +// TypeError 4731: (30-31): The function "f" does not have any parameters, and therefore cannot be attached to the type "Int". diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_or_returning_different_types.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_or_returning_different_types.sol new file mode 100644 index 000000000..a91d59936 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_or_returning_different_types.sol @@ -0,0 +1,20 @@ +type Int is int128; + +using { + add as +, + sub as -, + mul as *, + div as / +} for Int; + +function add(Int, int128) pure returns (Int) {} +function sub(int128, Int) pure returns (int128) {} +function mul(int128, int256) pure returns (Int) {} +function div(Int, Int) pure returns (int256) {} +// ---- +// TypeError 1884: (108-121): Wrong parameters in operator definition. The function "add" needs to have two parameters of type Int and the same data location to be used for the operator +. +// TypeError 1884: (156-169): Wrong parameters in operator definition. The function "sub" needs to have one or two parameters of type Int and the same data location to be used for the operator -. +// TypeError 7743: (183-191): Wrong return parameters in operator definition. The function "sub" needs to return exactly one value of type Int to be used for the operator -. +// TypeError 1884: (207-223): Wrong parameters in operator definition. The function "mul" needs to have two parameters of type Int and the same data location to be used for the operator *. +// TypeError 7743: (237-242): Wrong return parameters in operator definition. The function "mul" needs to return a value of the same type and data location as its parameters to be used for the operator *. +// TypeError 7743: (282-290): Wrong return parameters in operator definition. The function "div" needs to return exactly one value of type Int to be used for the operator /. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_two_parameters_unary.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_two_parameters_unary.sol new file mode 100644 index 000000000..734321a54 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_taking_two_parameters_unary.sol @@ -0,0 +1,14 @@ +type Int is int128; + +using {bitnot as ~} for Int; + +function bitnot(Int, Int) pure returns (Int) {} + +contract C { + function test() public pure { + ~Int.wrap(1); + } +} +// ---- +// TypeError 1884: (66-76): Wrong parameters in operator definition. The function "bitnot" needs to have exactly one parameter of type Int to be used for the operator ~. +// TypeError 4907: (155-167): Built-in unary operator ~ cannot be applied to type Int. No matching user-defined operator found. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_global.sol b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_global.sol new file mode 100644 index 000000000..c99fd0e68 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_global.sol @@ -0,0 +1,13 @@ +type Int is int16; + +function add(Int, Int) pure returns (Int) {} + +contract C { + using {add as +} for Int global; + + function test() pure public { + Int.wrap(0) + Int.wrap(0); + } +} +// ---- +// SyntaxError 3367: (83-115): "global" can only be used at file level. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_global_different_file.sol b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_global_different_file.sol new file mode 100644 index 000000000..96f474483 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_global_different_file.sol @@ -0,0 +1,13 @@ +==== Source: s1.sol ==== +type Bool is bool; + +==== Source: s2.sol ==== +import "s1.sol"; + +function not(Bool) pure returns (Bool) {} + +contract C { + using {not as !} for Bool global; +} +// ---- +// SyntaxError 3367: (s2.sol:78-111): "global" can only be used at file level. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_in_base_contract.sol b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_in_base_contract.sol new file mode 100644 index 000000000..c71d69a10 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_in_base_contract.sol @@ -0,0 +1,28 @@ +type Int is int128; + +function add(Int, Int) pure returns (Int) {} +function another_add(Int, Int) pure returns (Int) {} + +contract B { + using {add as +} for Int; + + function f() pure public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} + +contract C is B { + using {another_add as +} for Int; + + function g() pure public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} + +contract D is B { + function h() pure public returns (Int) { + return Int.wrap(0) + Int.wrap(0); + } +} +// ---- +// TypeError 2271: (491-516): Built-in binary operator + cannot be applied to types Int and Int. No matching user-defined operator found. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_in_interface.sol b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_in_interface.sol new file mode 100644 index 000000000..cb47d05b9 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_in_interface.sol @@ -0,0 +1,9 @@ +type Int is int; + +function add(Int, Int) pure returns (Int) {} + +interface I { + using {add as +} for Int; +} +// ---- +// SyntaxError 9088: (82-107): The "using for" directive is not allowed inside interfaces. diff --git a/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_in_library.sol b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_in_library.sol new file mode 100644 index 000000000..3096656d3 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_contract_level_in_library.sol @@ -0,0 +1,8 @@ +type Int is int; + +library L { + using {add as +} for Int; + + function add(Int, Int) internal pure returns (Int) {} + function unsub(Int) internal pure returns (Int) {} +} diff --git a/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_file_level_global_different_file.sol b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_file_level_global_different_file.sol new file mode 100644 index 000000000..46ec095ab --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/using_for_with_operator_at_file_level_global_different_file.sol @@ -0,0 +1,11 @@ +==== Source: s1.sol ==== +type Bool is bool; + +==== Source: s2.sol ==== +import "s1.sol"; + +function not(Bool) pure returns (Bool) {} + +using {not as !} for Bool global; +// ---- +// TypeError 4117: (s2.sol:61-94): Can only use "global" with types defined in the same source unit at file level. diff --git a/test/libsolidity/syntaxTests/using/using_for_enum.sol b/test/libsolidity/syntaxTests/using/using_for_enum.sol new file mode 100644 index 000000000..e7c6b5c82 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/using_for_enum.sol @@ -0,0 +1,5 @@ +enum E {A, B, C} + +function f(E) {} + +using {f} for E; diff --git a/test/libsolidity/syntaxTests/viewPureChecker/user_operator_with_pure_modifier_can_be_restricted.sol b/test/libsolidity/syntaxTests/viewPureChecker/user_operator_with_pure_modifier_can_be_restricted.sol new file mode 100644 index 000000000..cf0cdefbe --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/user_operator_with_pure_modifier_can_be_restricted.sol @@ -0,0 +1,19 @@ +type Int is uint8; + +using { + add as + +} for Int; + +function add(Int, Int) pure returns (Int) { + return Int.wrap(0); +} + +function f() pure { + Int.wrap(0) + Int.wrap(1); +} + +function g() { + Int.wrap(0) + Int.wrap(1); +} +// ---- +// Warning 2018: (178-225): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/viewPureChecker/user_operator_with_view_modifier.sol b/test/libsolidity/syntaxTests/viewPureChecker/user_operator_with_view_modifier.sol new file mode 100644 index 000000000..dbe7796f6 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/user_operator_with_view_modifier.sol @@ -0,0 +1,17 @@ +type Int is uint8; + +using { + add as + +} for Int; + + +function f_view() view {} + +function add(Int, Int) view returns (Int) { + f_view(); + return Int.wrap(0); +} + +function f() view { + Int.wrap(0) + Int.wrap(0); +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/user_operator_with_view_modifier_can_be_restricted.sol b/test/libsolidity/syntaxTests/viewPureChecker/user_operator_with_view_modifier_can_be_restricted.sol new file mode 100644 index 000000000..95063d44c --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/user_operator_with_view_modifier_can_be_restricted.sol @@ -0,0 +1,28 @@ +type Int is uint8; + +using { + add as + +} for Int; + + +function f_view() view {} + +function add(Int, Int) view returns (Int) { + f_view(); + return Int.wrap(0); +} + +function f() view { + Int.wrap(0) + Int.wrap(0); +} + +function g() { + Int.wrap(0) + Int.wrap(0); +} + +function h() pure { + Int.wrap(0) + Int.wrap(0); +} +// ---- +// Warning 2018: (220-267): Function state mutability can be restricted to view +// TypeError 2527: (293-318): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".