diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 5ccd8e285..8fe11757a 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -3059,6 +3059,19 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) solUnimplementedAssert(false, "Tuple conversion not implemented."); break; } + case Type::Category::TypeType: + { + TypeType const& typeType = dynamic_cast(_from); + if ( + auto const* contractType = dynamic_cast(typeType.actualType()); + contractType->contractDefinition().isLibrary() && + _to == *TypeProvider::address() + ) + body = "converted := value"; + else + solAssert(false, "Invalid conversion from " + _from.canonicalName() + " to " + _to.canonicalName()); + break; + } default: solAssert(false, "Invalid conversion from " + _from.canonicalName() + " to " + _to.canonicalName()); } diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 142660749..f81079d3e 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -838,10 +838,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) { solAssert(!functionType->bound(), ""); if (auto contractType = dynamic_cast(expressionType->actualType())) - solUnimplementedAssert( - !contractType->contractDefinition().isLibrary() || functionType->kind() == FunctionType::Kind::Internal, - "Only internal function calls implemented for libraries" - ); + if (contractType->contractDefinition().isLibrary()) + solAssert(functionType->kind() == FunctionType::Kind::Internal || functionType->kind() == FunctionType::Kind::DelegateCall, ""); } } else @@ -2146,9 +2144,10 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier) } else if (VariableDeclaration const* varDecl = dynamic_cast(declaration)) handleVariableReference(*varDecl, _identifier); - else if (dynamic_cast(declaration)) + else if (auto const* contract = dynamic_cast(declaration)) { - // no-op + if (contract->isLibrary()) + define(IRVariable(_identifier).part("address")) << linkerSymbol(*contract) << "\n"; } else if (dynamic_cast(declaration)) { @@ -2967,3 +2966,9 @@ void IRGeneratorForStatements::setLocation(ASTNode const& _node) { m_currentLocation = _node.location(); } + +string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const +{ + solAssert(_library.isLibrary(), ""); + return "linkersymbol(" + util::escapeAndQuoteString(_library.fullyQualifiedName()) + ")"; +} diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index 3d87eae57..21386dd6c 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -184,6 +184,8 @@ private: void setLocation(ASTNode const& _node); + std::string linkerSymbol(ContractDefinition const& _library) const; + std::ostringstream m_code; IRGenerationContext& m_context; YulUtilFunctions& m_utils; diff --git a/test/libsolidity/semanticTests/freeFunctions/libraries_from_free.sol b/test/libsolidity/semanticTests/freeFunctions/libraries_from_free.sol index 3632f6a6a..861313e92 100644 --- a/test/libsolidity/semanticTests/freeFunctions/libraries_from_free.sol +++ b/test/libsolidity/semanticTests/freeFunctions/libraries_from_free.sol @@ -16,6 +16,8 @@ contract C { return fu(); } } +// ==== +// compileViaYul: also // ---- // library: L -// f() -> 7, 8 \ No newline at end of file +// f() -> 7, 8 diff --git a/test/libsolidity/semanticTests/libraries/external_call_with_function_pointer_parameter.sol b/test/libsolidity/semanticTests/libraries/external_call_with_function_pointer_parameter.sol new file mode 100644 index 000000000..a0843bfcb --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/external_call_with_function_pointer_parameter.sol @@ -0,0 +1,26 @@ +library L { + function run( + function(uint256) external returns (uint256) _operation, + uint256 _a + ) + external + returns (uint256) + { + return _operation(_a); + } +} + +contract C { + function double(uint256 _a) external returns (uint256) { + return _a * _a; + } + + function g(uint256 _value) external returns (uint256) { + return L.run(this.double, _value); + } +} +// ==== +// compileViaYul: also +// ---- +// library: L +// g(uint256): 4 -> 16 diff --git a/test/libsolidity/semanticTests/libraries/external_call_with_storage_array_parameter.sol b/test/libsolidity/semanticTests/libraries/external_call_with_storage_array_parameter.sol new file mode 100644 index 000000000..81268af7a --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/external_call_with_storage_array_parameter.sol @@ -0,0 +1,19 @@ +library L { + function f(uint256[2] storage _a) external returns (uint256) { + return _a[0] * _a[1]; + } +} + +contract C { + uint256[2] x; + + function g(uint256 _value) external returns (uint256) { + x[0] = x[1] = _value; + return L.f(x); + } +} +// ==== +// compileViaYul: also +// ---- +// library: L +// g(uint256): 4 -> 16 diff --git a/test/libsolidity/semanticTests/libraries/library_address_homestead.sol b/test/libsolidity/semanticTests/libraries/library_address_homestead.sol index ce7344f4a..256b43d3a 100644 --- a/test/libsolidity/semanticTests/libraries/library_address_homestead.sol +++ b/test/libsolidity/semanticTests/libraries/library_address_homestead.sol @@ -12,6 +12,8 @@ contract C { return success; } } +// ==== +// compileViaYul: also // ---- // library: L // g(uint256,uint256): 1, 1 -> true diff --git a/test/libsolidity/semanticTests/libraries/library_address_via_module.sol b/test/libsolidity/semanticTests/libraries/library_address_via_module.sol new file mode 100644 index 000000000..1a6c3ee41 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/library_address_via_module.sol @@ -0,0 +1,60 @@ +==== Source: a.sol ==== + +import "a.sol" as M; + +library L { + function f(uint256 v) external pure returns (uint) { + return v * v; + } + function g(uint256 v) external returns (uint) { + return v * v; + } +} +contract C { + function addr() public view returns (bool) { + return address(M.L) == address(0); + } + function g(uint256 v) public view returns (uint256) { + return M.L.f(v); + } + function h(uint256 v) public returns (uint256) { + (bool success, bytes memory result) = address(M.L).delegatecall(abi.encodeWithSignature("f(uint256)", v)); + assert(success); + return abi.decode(result, (uint256)); + } + function i(uint256 v) public returns (uint256) { + (bool success, bytes memory result) = address(M.L).call(abi.encodeWithSignature("f(uint256)", v)); + assert(success); + return abi.decode(result, (uint256)); + } + function j(uint256 v) public returns (uint256) { + (bool success, bytes memory result) = address(M.L).delegatecall(abi.encodeWithSignature("g(uint256)", v)); + assert(success); + return abi.decode(result, (uint256)); + } + function k(uint256 v) public returns (uint256) { + (bool success, bytes memory result) = address(M.L).call(abi.encodeWithSignature("g(uint256)", v)); + assert(success); + return abi.decode(result, (uint256)); + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// library: L +// addr() -> false +// g(uint256): 1 -> 1 +// g(uint256): 2 -> 4 +// g(uint256): 4 -> 16 +// h(uint256): 1 -> 1 +// h(uint256): 2 -> 4 +// h(uint256): 4 -> 16 +// i(uint256): 1 -> 1 +// i(uint256): 2 -> 4 +// i(uint256): 4 -> 16 +// j(uint256): 1 -> 1 +// j(uint256): 2 -> 4 +// j(uint256): 4 -> 16 +// k(uint256): 1 -> FAILURE +// k(uint256): 2 -> FAILURE +// k(uint256): 4 -> FAILURE diff --git a/test/libsolidity/semanticTests/libraries/stub.sol b/test/libsolidity/semanticTests/libraries/stub.sol index 8bae3df27..4ed1f2673 100644 --- a/test/libsolidity/semanticTests/libraries/stub.sol +++ b/test/libsolidity/semanticTests/libraries/stub.sol @@ -6,6 +6,8 @@ contract C { return L.f(v); } } +// ==== +// compileViaYul: also // ---- // library: L // g(uint256): 1 -> 1 diff --git a/test/libsolidity/syntaxTests/functionTypes/external_library_function_to_external_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/external_library_function_to_external_function_type.sol new file mode 100644 index 000000000..dbc873b39 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_library_function_to_external_function_type.sol @@ -0,0 +1,14 @@ +library L { + function f(uint256 _a) external returns (uint256) {} +} + +contract C { + function run(function(uint256) external returns (uint256) _operation) internal returns (uint256) {} + function test() public { + run(L.f); + function(uint256) external returns (uint256) _operation = L.f; + } +} +// ---- +// TypeError 9553: (230-233): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) returns (uint256) to function (uint256) external returns (uint256) requested. +// TypeError 9574: (244-305): Type function (uint256) returns (uint256) is not implicitly convertible to expected type function (uint256) external returns (uint256). diff --git a/test/libsolidity/syntaxTests/types/address/contract_type_to_address.sol b/test/libsolidity/syntaxTests/types/address/contract_type_to_address.sol new file mode 100644 index 000000000..62b34a294 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/contract_type_to_address.sol @@ -0,0 +1,21 @@ +interface I {} + +library L {} + +contract C { + function f() public pure { + address(C); + address(I); + address(L); // This one is allowed + + address(type(C)); + address(type(I)); + address(type(L)); + } +} +// ---- +// TypeError 9640: (82-92): Explicit type conversion not allowed from "type(contract C)" to "address". +// TypeError 9640: (102-112): Explicit type conversion not allowed from "type(contract I)" to "address". +// TypeError 9640: (166-182): Explicit type conversion not allowed from "type(contract C)" to "address". +// TypeError 9640: (192-208): Explicit type conversion not allowed from "type(contract I)" to "address". +// TypeError 9640: (218-234): Explicit type conversion not allowed from "type(library L)" to "address". diff --git a/test/libsolidity/syntaxTests/types/address/super_to_address.sol b/test/libsolidity/syntaxTests/types/address/super_to_address.sol new file mode 100644 index 000000000..7ffcd4ece --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/super_to_address.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + address(super); + } +} +// ---- +// TypeError 9640: (52-66): Explicit type conversion not allowed from "contract super C" to "address". diff --git a/test/libsolidity/syntaxTests/types/address/type_type_to_address.sol b/test/libsolidity/syntaxTests/types/address/type_type_to_address.sol new file mode 100644 index 000000000..7f4666a54 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/type_type_to_address.sol @@ -0,0 +1,46 @@ +struct S { + uint x; +} + +enum E {A, B, C} + +contract C { + function f() public pure { + address(uint); + address(bytes16); + address(bool); + address(address); + address(fixed); + + address(S); + address(E); + + address(uint[]); + address(uint[][]); + address(uint[5]); + address(string); + address(bytes); + address(S[]); + address(E[]); + address((uint, uint)); + + address(type(uint)); + } +} +// ---- +// TypeError 9640: (96-109): Explicit type conversion not allowed from "type(uint256)" to "address". +// TypeError 9640: (119-135): Explicit type conversion not allowed from "type(bytes16)" to "address". +// TypeError 9640: (145-158): Explicit type conversion not allowed from "type(bool)" to "address". +// TypeError 9640: (168-184): Explicit type conversion not allowed from "type(address)" to "address". +// TypeError 9640: (194-208): Explicit type conversion not allowed from "type(fixed128x18)" to "address". +// TypeError 9640: (219-229): Explicit type conversion not allowed from "type(struct S storage pointer)" to "address". +// TypeError 9640: (239-249): Explicit type conversion not allowed from "type(enum E)" to "address". +// TypeError 9640: (260-275): Explicit type conversion not allowed from "type(uint256[] memory)" to "address". +// TypeError 9640: (285-302): Explicit type conversion not allowed from "type(uint256[] memory[] memory)" to "address". +// TypeError 9640: (312-328): Explicit type conversion not allowed from "type(uint256[5] memory)" to "address". +// TypeError 9640: (338-353): Explicit type conversion not allowed from "type(string storage pointer)" to "address". +// TypeError 9640: (363-377): Explicit type conversion not allowed from "type(bytes storage pointer)" to "address". +// TypeError 9640: (387-399): Explicit type conversion not allowed from "type(struct S memory[] memory)" to "address". +// TypeError 9640: (409-421): Explicit type conversion not allowed from "type(enum E[] memory)" to "address". +// TypeError 9640: (431-452): Explicit type conversion not allowed from "tuple(type(uint256),type(uint256))" to "address". +// TypeError 9640: (463-482): Explicit type conversion not allowed from "type(uint256)" to "address".